0

3つのタブがあるAndroidアプリケーションがあります。これらはアクティビティ(TabsFragmentActivity)を使用して作成され、各タブのインターフェイスはフラグメント(TabProfile、TabSearch、およびTabLocationsフラグメント)を使用して作成されます。

フラグメントの1つ(TabLocations)で、AsyncTaskを開始します。ユーザーが別のタブに切り替えたら、AsyncTaskをキャンセルできるようにしたいと思います。タブにデータを入力するアクティビティ(TabsFragmentActivity)を介してこれを行う方法はありますか?

TabsFragmentActivityアクティビティからAsyncTaskのステータスを確認する必要があると思いますが、AsyncTaskはアクティビティ自体ではなく、フラグメントの1つで開始されるため、これを行う方法がわかりません。私が今抱えている問題は、非同期タスクでいくつかのリストビューにデータを入力しようとし、ユーザーがタブを切り替えてもリストビューが画面に表示されないことです。

TabFragmentActivity.java

package com.example.q;

import java.util.HashMap;

import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.View;
import android.widget.TabHost;
import android.widget.TabHost.TabContentFactory;

import com.parse.Parse;
import com.parse.ParseACL;
import com.parse.ParseUser;

public class TabsFragmentActivity extends FragmentActivity implements TabHost.OnTabChangeListener {
    private static final String TAG = "TabsFragmentActivity";

    private TabHost mTabHost;
    private HashMap mapTabInfo = new HashMap();
    private TabInfo mLastTab = null;

    private class TabInfo {
         private String tag;
         private Class clss;
         private Bundle args;
         private Fragment fragment;
         TabInfo(String tag, Class clazz, Bundle args) {
             this.tag = tag;
             this.clss = clazz;
             this.args = args;
         }

    }

    class TabFactory implements TabContentFactory {

        private final Context mContext;

        /**
         * @param context
         */
        public TabFactory(Context context) {
            mContext = context;
        }

        /** (non-Javadoc)
         * @see android.widget.TabHost.TabContentFactory#createTabContent(java.lang.String)
         */
        public View createTabContent(String tag) {
            View v = new View(mContext);
            v.setMinimumWidth(0);
            v.setMinimumHeight(0);
            return v;
        }

    }
    /** (non-Javadoc)
     * @see android.support.v4.app.FragmentActivity#onCreate(android.os.Bundle)
     */
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Step 1: Inflate layout
        setContentView(R.layout.tabs_layout);
        // Step 2: Setup TabHost
        initialiseTabHost(savedInstanceState);
        mTabHost.setCurrentTab(1);
        if (savedInstanceState != null) {
            //mTabHost.setCurrentTab(1);
            mTabHost.setCurrentTabByTag(savedInstanceState.getString("tab")); //set the tab as per the saved state
        }
        // initialize Parse
        Log.d(TAG, "initializing Parse");
        Parse.initialize(this, "rReToGbnCSdQEi7Q33UrCO4U395Rk7RcKPcNncOn", "haJKaN0zbNKhgBT1t9jGUY0ih4rYQfPMA9p31BSw"); 

        ParseUser.enableAutomaticUser();
        ParseACL defaultACL = new ParseACL();

        // If you would like all objects to be private by default, remove this line.
        defaultACL.setPublicReadAccess(true);

        ParseACL.setDefaultACL(defaultACL, true);    
    }

    /** (non-Javadoc)
     * @see android.support.v4.app.FragmentActivity#onSaveInstanceState(android.os.Bundle)
     */
    protected void onSaveInstanceState(Bundle outState) {
        outState.putString("tab", mTabHost.getCurrentTabTag()); //save the tab selected
        super.onSaveInstanceState(outState);
    }

    /**
     * Step 2: Setup TabHost
     */
    private void initialiseTabHost(Bundle args) {
        mTabHost = (TabHost)findViewById(android.R.id.tabhost);
        mTabHost.setup();
        TabInfo tabInfo = null;
        TabsFragmentActivity.addTab(this, this.mTabHost, this.mTabHost.newTabSpec("Tab1").
                setIndicator("", getResources().getDrawable(R.drawable.profile)), (tabInfo = new TabInfo("Tab1", TabProfile.class, args)));
        this.mapTabInfo.put(tabInfo.tag, tabInfo);
        TabsFragmentActivity.addTab(this, this.mTabHost, this.mTabHost.newTabSpec("Tab2").
                setIndicator("", getResources().getDrawable(R.drawable.locations) ), (tabInfo = new TabInfo("Tab2", TabLocations.class, args)));
        this.mapTabInfo.put(tabInfo.tag, tabInfo);
        TabsFragmentActivity.addTab(this, this.mTabHost, this.mTabHost.newTabSpec("Tab3").
                setIndicator("", getResources().getDrawable(R.drawable.search)), (tabInfo = new TabInfo("Tab3", TabSearch.class, args)));
        this.mapTabInfo.put(tabInfo.tag, tabInfo);

        // Default to the second tab
        this.onTabChanged("Tab2");

        mTabHost.setOnTabChangedListener(this);
    }

    /**
     * @param activity
     * @param tabHost
     * @param tabSpec
     * @param clss
     * @param args
     */
    private static void addTab(TabsFragmentActivity activity, TabHost tabHost, TabHost.TabSpec tabSpec, TabInfo tabInfo) {
        // Attach a Tab view factory to the spec
        tabSpec.setContent(activity.new TabFactory(activity));
        String tag = tabSpec.getTag();

        // Check to see if we already have a fragment for this tab, probably
        // from a previously saved state.  If so, deactivate it, because our
        // initial state is that a tab isn't shown.
        tabInfo.fragment = activity.getSupportFragmentManager().findFragmentByTag(tag);
        if (tabInfo.fragment != null && !tabInfo.fragment.isDetached()) {
            FragmentTransaction ft = activity.getSupportFragmentManager().beginTransaction();
            ft.detach(tabInfo.fragment);
            ft.commit();
            activity.getSupportFragmentManager().executePendingTransactions();
        }

        tabHost.addTab(tabSpec);
    }

    /** (non-Javadoc)
     * @see android.widget.TabHost.OnTabChangeListener#onTabChanged(java.lang.String)
     */
    public void onTabChanged(String tag) {
        Log.d(TAG, "in onTabChanged");
        TabInfo newTab = (TabInfo) this.mapTabInfo.get(tag);
        if (mLastTab != newTab) {
            Log.d(TAG, "switching to new tab");
            FragmentTransaction ft = this.getSupportFragmentManager().beginTransaction();
            if (mLastTab != null) {
                Log.d(TAG, "last tab not null");
                if (mLastTab.fragment != null) {
                    Log.d(TAG, "last tab fragment not null");
                    ft.detach(mLastTab.fragment);
                }
            }
            if (newTab != null) {
                if (newTab.fragment == null) {
                    newTab.fragment = Fragment.instantiate(this,
                            newTab.clss.getName(), newTab.args);
                    ft.add(R.id.realtabcontent, newTab.fragment, newTab.tag);
                } else {
                    ft.attach(newTab.fragment);
                }
            }

            mLastTab = newTab;
            ft.commit();
            this.getSupportFragmentManager().executePendingTransactions();
        }
    }


}

TabLocations.java(このファイルにはたくさんあるので、わかりやすくするためにほとんど編集しました):

public class TabLocations extends Fragment {

    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        if (container == null) {
            return null;
        }
        return (RelativeLayout)inflater.inflate(R.layout.tab_locations_layout, container, false);
    }


    @Override
    public void onActivityCreated(Bundle savedInstanceState) {

        // Run AsyncTask for getting Google Places
        FetchGooglePlaces places = new FetchGooglePlaces(getActivity());
        places.execute();

 }       


}

FetchGooglePlaces.java-私のAsyncTask

package com.example.q;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;

import android.app.Activity;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.os.AsyncTask;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.Toast;

import com.parse.FindCallback;
import com.parse.GetCallback;
import com.parse.ParseException;
import com.parse.ParseObject;
import com.parse.ParseQuery;


public class FetchGooglePlaces extends AsyncTask<String, PlacesList, String>{

    private static final String TAG = "FetchGooglePlaces";

     // Google Places
     GooglePlaces googlePlaces;

     // Places List
     public PlacesList nearPlaces;

     // GPS Location
     GPSTracker gps;

     // Progress layouts for qlocations and alocations
     LinearLayout qProgress;
     LinearLayout aProgress;

     // KEY Strings
     public static String KEY_REFERENCE = "reference"; // id of the place
     public static String KEY_NAME = "name"; // name of the place

     // ListView of all q locations detected
     ListView qLV;

     // ListView of all all non-q locations detected
     ListView allLV;

     // Refresh Button
     Button refresh;

     // TabLocations activity
     public Activity activity;

     PlacesDBHelper placesDBHelper;
     SQLiteDatabase db;

     // ArrayList to store the names of qLocations
     ArrayList<String[]> qLocations;

     //ArrayList for storing QLocations
     ArrayList<QLocation> qLocationData = new ArrayList<QLocation>();

     //Temporary ArrayList for storing QLocations
     ArrayList<String[]> qLocationDataString = new ArrayList<String[]>();

     //ArrayList for storing allLocations
     ArrayList<QLocation> allLocationData = new ArrayList<QLocation>();

     //Temporary ArrayList for storing allLocations
     ArrayList<String[]> allLocationDataString = new ArrayList<String[]>();

     boolean done = false;

     boolean checking = true;

     int counter = 0;

     public FetchGooglePlaces(Activity a){
         activity = a;
     }

    /**
     * Before starting background thread Show Progress Dialog
     * */
    @Override
    protected void onPreExecute() {
        super.onPreExecute();

//        placesDBHelper = new PlacesDBHelper(activity);
//        Log.d(TAG, "attempting to create database");
//        
//        Log.d(TAG, "placesDBHelper: " + placesDBHelper.getDatabaseName());

        // set visibility of progress bars
        qProgress = (LinearLayout) activity.findViewById(R.id.lin_progressBar);
        qProgress.setVisibility(View.VISIBLE);
        aProgress = (LinearLayout) activity.findViewById(R.id.lin_progressBar2);
        aProgress.setVisibility(View.VISIBLE);

        // creating GPS Class object
        gps = new GPSTracker(activity);
    }

    /**
     * getting Places JSON
     * */
    protected String doInBackground(String... args) {
        // creating Places class object
        googlePlaces = new GooglePlaces();

        try {
            Log.d(TAG, "getting google places");
            String types = "cafe|restaurant"; // Listing places only cafes, restaurants

            // Radius in meters - increase this value if you don't find any places
            double radius = 1000; // 1000 meters 

            // get nearest places
            nearPlaces = googlePlaces.search(gps.getLatitude(),
                    gps.getLongitude(), radius, types);

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * After completing background task Dismiss the progress dialog
     * and show the data in UI
     * Always use runOnUiThread(new Runnable()) to update UI from background
     * thread, otherwise you will get error
     * **/
    protected void onPostExecute(String file_url) {
        Log.d(TAG, "complete");         

        /**
         * Updating parsed Places into LISTVIEW
         * */
        // Get json response status
         String status = nearPlaces.status;

        // Check for all possible status
        if(status.equals("OK")){
            // Successfully got places details
            if (nearPlaces.results != null) {

                // get current list of Q Locations + their wait times
                qLocations = new ArrayList<String[]>();
                ParseQuery qs = new ParseQuery("QLocations");
                //EDIT: THIS SHOULD ONLY QUERY LOCATIONS THAT ARE CLOSEBY (TO MINIMIZE SEARCH TIME)
                qs.findInBackground(new FindCallback() {

                    @Override
                    public void done(final List<ParseObject> qList, ParseException e) {                        
                        if (e==null){

                            // add each parse location to the qLocations array
                            for(int i= 0; i < qList.size(); i++){
                                if(checking){
                                        final String name = qList.get(i).getString("name");
                                        checking = false;

                                        //get queue length for each location
                                        ParseObject place = qList.get(i);

                                        place.getParseObject("Line").fetchIfNeededInBackground(new GetCallback() {                                            
                                            @Override
                                            public void done(ParseObject object, ParseException e) {
                                                String lineLength = Integer.toString(object.getInt("length"));
                                                String[] locationArray = new String[] {name, lineLength};
                                                qLocations.add(locationArray);
                                                //Log.d(TAG, "added " + qLocations.get(qLocations.size()-1)[0] + " to qLocations");
                                                counter++;
                                                if (counter == qList.size()){
                                                    drawListViews();                                                    
                                                }
                                            }
                                        });
                                        checking = true;
                                    }
                            }                            
                        }
                        else{
                            Log.d("Error", "Error: " + e.getMessage());
                        }  
                        }
                    });
            }
        }
        else{
            Toast.makeText(activity, "Google Places Error!", Toast.LENGTH_SHORT);
        }
    }

    public void drawListViews(){

        Log.d(TAG, "in drawListViews()");

        // loop through each place
        int counter = 0;   

        for (Place p : nearPlaces.results) {

            //limit to 10 search results
            if (counter<9){
                  HashMap<String, String> map = new HashMap<String, String>();  

                // Place reference won't display in listview - it will be hidden
                // Place reference is used to get "place full details"
                map.put(KEY_REFERENCE, p.reference);

                // Place name
                map.put(KEY_NAME, p.name);

                boolean placeExists = false;
                String lineLength = "";

                for(int i=0; i<qLocations.size(); i++){
                    // if the google places exists as a Q
                    if (p.name.equals(qLocations.get(i)[0])){
                        placeExists = true;
                        lineLength = qLocations.get(i)[1];
                        break;
                    }
                }
                if (placeExists){
                    // add to qLocationData array
                    qLocationDataString.add(new String[] {p.name, p.reference, lineLength});
                }else{
                    // add to allLocationData array
                    allLocationDataString.add(new String[] {p.name, p.reference, lineLength});
                }

        }else{
                break;
        }
            counter++;
        }

        //sort qLocationDataString by length of line
        Collections.sort(qLocationDataString, new Comparator<String[]>(){
            public int compare(String[] strings, String[] otherStrings){
                return Integer.valueOf(strings[2]).compareTo(Integer.valueOf(otherStrings[2]));
            }
        });

        // add sorted qLocationDataString to qLocationData to pass to the array adapter
        for(int i=0; i<qLocationDataString.size(); i++){
            qLocationData.add(new QLocation(qLocationDataString.get(i)[0], qLocationDataString.get(i)[1], qLocationDataString.get(i)[2] ));
        }

        //sort allLocationDataString alphabetically
        Collections.sort(allLocationDataString, new Comparator<String[]>(){
            public int compare(String[] strings, String[] otherStrings){
                return strings[0].compareTo(otherStrings[0]);
            }
        });


        // add sorted allLocationDataString to allLocationData to pass to the array adapter
        for(int i=0; i<allLocationDataString.size(); i++){
            allLocationData.add(new QLocation(allLocationDataString.get(i)[0], allLocationDataString.get(i)[1], allLocationDataString.get(i)[2] ));
        }

        // Getting qListView: List View for locations with Qs
        qLV = (ListView) activity.findViewById(R.id.qListView);

        // list adapter
        ListAdapter qAdapter = new QAdapter(activity, R.layout.google_places_item, qLocationData, "qs"); 

        // Adding data into listview
        qLV.setAdapter(qAdapter);

        // Getting allListView: List View for locations without Qs
        allLV = (ListView) activity.findViewById(R.id.allListView);

        // list adapter
        ListAdapter allAdapter = new QAdapter(activity, R.layout.google_places_item, allLocationData, "all");

        // Adding data into listview
        allLV.setAdapter(allAdapter);

        // hide progress bars
        qProgress.setVisibility(View.GONE);
        aProgress.setVisibility(View.GONE);

//        // show refresh button
//        refresh = (Button) activity.findViewById(R.id.refreshButton);
//        refresh.setVisibility(View.VISIBLE);

        returnPlaces(nearPlaces);

        Button maps = (Button) activity.findViewById(R.id.btn_show_map);

        /** Button click event for showing map */
            maps.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View view) {
                Log.d("attempting to create new intent", "show map");
            Intent i = new Intent(activity,
                    QMapActivity.class);
            // Sending user current geo location
            i.putExtra("user_latitude", Double.toString(gps.getLatitude()));
            i.putExtra("user_longitude", Double.toString(gps.getLongitude()));

            // passing near places to map activity
            i.putExtra("near_places", nearPlaces);
            // pass list of q locations to map activity
            i.putExtra("q_places", qLocationDataString);

            Log.d(TAG, nearPlaces.toString());
            // staring activity
            activity.startActivity(i);
        }
    });

}




    private PlacesList returnPlaces(PlacesList places){
        return places;
    }


}
4

2 に答える 2

1

これを行うには、インスタンスをアプリケーションコンテキストに保存します。これは、おっとの概念としては不適切です。アクティビティでAsyncTaskのインスタンスを作成し、フラグメントで実行することもできます

class TabsFragmentActivity extends FragmentActivity implements TabHost.OnTabChangeListener{
    private static FetchGooglePlaces task;
        task=new FetchGooglePlaces ();//Create but not execute.
//You can decide to cancel it when onTabChange triggers with task.cancel();

}
class TabLocations extends Fragment {
        void onCreate(){
            TabsFragmentActivity .getTask().execute; //execute it here.
        }
}
于 2013-01-28T20:35:42.460 に答える
1

フラグメントのライフサイクルライフサイクルを見てください。onStop()またはonPause()オーバーライドされたメソッドの間に非同期タスクを停止することを考えましたか?

于 2013-01-28T20:36:56.797 に答える