0

I am trying to figure out a way to get specific values that are needed for the objects displayed in a ListView. In the example below, I am building a list of users. I use an existing array to supply some of the values but need to dynamically check for/get pictures associated with that user from the server.

private void getUsers(JSONArray userArray){
    users = new ArrayList<User>();
    int length = userArray.length();
    if(DEBUG) Log.d(TAG, userArray.toString());
    try{

        for(int i = 0; i < length; i++){
            User u = new User();
            u.setProfileId(userArray.getJSONObject(i).getString("profileid"));
            u.setDisplayName(userArray.getJSONObject(i).getString("displayname"));
            u.setStatus(userArray.getJSONObject(i).getString("status"));
            u.setId(userArray.getJSONObject(i).getString("id"));
            if(memCache.contains(u.getDisplayName())){
                u.setProfilePicture(memCache.getBitmapFromMemCache(u.getDisplayName())); 
            } else {
                downloadPicture(u.getProfileId(), u.getDisplayName());
            }
            users.add(u);
        }
        users.add(createBlankUser());
        updateUserListView(); 
    } catch (Exception e) {
        Log.e("BACKGROUND_PROC", e.getMessage());
    }
}

private void downloadPicture(String profileId, final String displayName){
    GetUserProfilePicture getPic = new GetUserProfilePicture(new OnUserPictureDownloaded(){

        @Override
        public void downloadFinished(Bitmap b) {
            if(b != null){
                if(DEBUG) Log.d(TAG, "Download finished " + b.toString() + " " + displayName);
                memCache.addBitmapToMemoryCache(displayName, b);
            }
        }
    });
    getPic.execute(profileId);
}

The AsyncTask and methods in its class all do what they are supposed to. I get the image returned properly from the server. The issue is that I can't link the result of the AsyncTask to a particular object before I add it to the list. In case that made no sense, in the past when I was using a private AsyncTask within this activity I could just run any I/O and object building methods in the background together so that the downloading of the images would correspond to the object being constructed at that time. Now that I have made the AsyncTask its own class (which is better for the overall structure of the app) I'm having a hard time taking the value returned by the interface and using.

Any suggestions?

4

1 回答 1

1

如果我正确理解您的问题,您需要检测何时AsyncTask完成,传入您下载的值,并从那里进行适当的对象初始化。

我实现这一点的方法是通过我命名的自定义界面OnTaskFinishedListener。在 的构造函数中AsyncTask,我传入一个Activity引用(如果在 a 中,Fragment我也传入一个Fragment引用),并根据代码是在 an还是 a中,将引用OnTaskFinishedListener转换为我的Activity引用或我的引用。之后,我在or中实现接口,我需要在其中接收回调并在那里进行初始化。用代码解释总是更容易,所以这里是:FragmentActivityFragmentActivityFragment

public interface OnTaskFinishedListener {
    /* Pass our information to the Activity or Fragment that started this 
    AsyncTask once our custom Asynctask finishes.*/
    public void onTaskFinished(/*Varargs or variable(s) as parameter(s)*/);
}

public class CustomTask extends AsyncTask<Object, Integer, Object> {
    Activity activity;
    Fragment fragment;
    OnTaskFinishedListener mListener;

    // Running the task from an activity
    public CustomTask(Activity activity) {
         this.activity = activity;
         try {
             mListener = (OnTaskFinishedListener) activity;
         } catch (ClassCastException e) {
             Log.e(SOME_TAG, activity.toString() + " must implement " +
             "OnTaskFinishedListener."
             e.printStackTrace();
         }
    }

    // Running the task from a Fragment
    public CustomTask(Activity activity, Fragment fragment) {
        this.activity = activity;
        this.fragment = fragment;

        try {
             mListener = (OnTaskFinishedListener) fragment;
         } catch (ClassCastException e) {
             Log.e(SOME_TAG, activity.toString() + " must implement " +
             "OnTaskFinishedListener."
             e.printStackTrace();
         }
    }

    ...

    protected Object doInBackground(Object... urls) {
        // Background work here
        return totalSize;
    }

    protected void onPostExecute(Object result) {
        mListener.onTaskFinished(result);
    }

public class MainActivity extends Activity {

     ...

    public void onTaskFinished(Object result) {
        // TODO object initialization, ListView backing, loops, etc.
    }

}

希望这可以帮助!

于 2013-06-14T16:57:17.547 回答