I have a list view populated with a database, with a custom cursor adapter, SavedTripsAdapter.

Here is how I initialized the adapter: allTrips = mDb.fetchAllTrips();

        String[] from = new String[] { "purp", "fancystart", "fancyinfo", "endtime", "start", "distance", "status" };
        int[] to = new int[] { R.id.TextViewPurpose, R.id.TextViewStart,
                R.id.TextViewInfo };

        sta = new SavedTripsAdapter(getActivity(),
                R.layout.saved_trips_list_item, allTrips, from, to,
                CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);

        lv.setAdapter(sta);

When I click on a list item, I can upload it again by calling this following function, which is completed in an AsyncTask.

In FragmentSavedTripsSection:

private void retryTripUpload(long tripId) {
    TripUploader uploader = new TripUploader(getActivity());
    uploader.execute();
}

In TripUploader:

@Override
protected void onPostExecute(Boolean result) {
    try {
        if (result) {
            Toast.makeText(mCtx.getApplicationContext(),"Trip uploaded successfully.", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(mCtx.getApplicationContext(),"Cycle Atlanta couldn't upload the trip, and will retry when your next trip is completed.", Toast.LENGTH_LONG).show();
        }
    } catch (Exception e) {
        // Just don't toast if the view has gone out of context
    }
}

However, the TripUploader is a separate class. When the trip is uploaded successfully, the database is updated, so I want to refresh the list using savedTripsAdapter.notifyDataSetChanged()

Where and how should put savedTripsAdapter.notifyDataSetChanged()?

If I put it in the list view class, it is not called onPostExecute. But if I put it in the TripUploader's onPostExecute function, how can I get access to the same instance of savedTripsAdapter, which I instantiated in the list view class?

Thanks for your help!

有帮助吗?

解决方案

The typical usage of notifyDataSetChanged() is to call it in the same class that handles your views.

For example, in your Fragment's onViewCreated(), you get a reference to the ListView and the adapter, and when you have your data ready, typically in the onPostExecute() you would call notifyDataSetChanged() to update the view.

If you prefer to pass your adapter to another object to do the data manipulation, you can just go ahead and do it, nothing special since java passes object by reference, so your Adapter object will be the same object in both classes

Edit:

My assumptions are:

  • your Adapter is called sta
  • your Fragment is called FragmentSavedTrips
  • your object that modifies the data is call SavedTripsChanger
  • your data string array is called from.

Inside SavedTripsChanger have a private variable to hold the adapter

private SavedTripsAdapter mSavedTripsAdapter;

and a setter method (optional getter method)

public SavedTripsAdapter setSavedTripsAdapter(SavedTripsAdapter mSavedTripsAdapter) {
     this.mSavedTripsAdapter = mSavedTripsAdapter;
}

When you create object SavedTripsChanger pass it the mSavedTripsAdapter instance, either in the constructor or using the setter method. Inside FragmentSavedTrips

SavedTripsChanger mSavedTripsChanger = new SavedTripsChanger();
mSavedTripsChanger.setSavedTripsAdapter(sta);

now you are ready to use it. After you are done modifying the data and ready to update the view inside SavedTripsChanger just call the notifyDataSetChanged()

mSavedTripsAdapter.notifyDataSetChanged();

其他提示

public class TripUploader extends AsyncTask<>{
    private listener;

    public interface YourListener{
       onCompleted(boolean result);
    }

    public TripUploader(YourListener listener){
       this.listener = listener;
    }

    protected onPostExecute(boolean result){
       listener.onCompleted(result);
    }
}

in your main class, implement this listener and implement the method, so whenever your asynctask finish, you'll receive it and you can make notifydatasetchange inside your class.

public class FragmentSavedTripsSection extends Fragment implements YourListener{

  public void onCompleted(boolean result){
       // notify data
  }
}

By using interface, you can use this class for other activities as well without coupling it to only one class.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top