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;
}
}