我可以在ListFragment中使用AsyncTask吗?或者我应该使用AsyncTaskLoader?

时间:2013-03-13 13:38:35

标签: android android-asynctask android-tabhost android-listfragment asynctaskloader

我尝试了下面的代码,并尝试了AsyncTaskLoader方法。当我实例化AsyncTask时,应用程序崩溃了。请告诉我关于在标签主机内的列表片段中加载JSON的最佳方法。

下面的代码是标签片段(我在主要活动中使用操作栏标签):

public class TabTop extends ListFragment {
Context context = getActivity().getBaseContext();
String API_URL = "http://api.rottentomatoes.com/api/public/v1.0/movies/770672122/similar.json?apikey=crhhxb4accwwa6cy6fxrm8vj&limit=1";
ArrayList<Deal> deals;
DealsListAdapter adapter;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        @SuppressWarnings("unused")
        int a = 0;
        return super.onCreateView(inflater, container, savedInstanceState);
}


@Override
public void onActivityCreated(Bundle savedInstanceState) {
    GetTopDeals getTopDeals = new GetTopDeals(context);
    getTopDeals.execute(API_URL);
    super.onActivityCreated(savedInstanceState);
}


class GetTopDeals extends AsyncTask<String, Void, ArrayList<Deal>>{
    ProgressDialog progressDialog;

    public GetTopDeals(Context activity) {
        this.progressDialog = new ProgressDialog(activity);
    }

    @Override
    protected void onPostExecute(ArrayList<Deal> result) {
        adapter = new DealsListAdapter(context, result);
        setListAdapter(adapter);
        super.onPostExecute(result);
    }

    @Override
    protected void onPreExecute() {
        progressDialog.setCancelable(true);
        progressDialog.setProgress(0);
        progressDialog.setMessage("loading Top deals...");
        progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        super.onPreExecute();
    }


    @Override
    protected ArrayList<Deal> doInBackground(String... urls) {
        String response = sendRequest(urls[0]); // make request for json
        return processResponse(response); // parse the Json and return ArrayList to postExecute

    }

    private String sendRequest(String apiUrl) {
        BufferedReader input = null; // get the json
        HttpURLConnection httpCon = null; // the http connection object
        StringBuilder response = new StringBuilder(); // hold all the data from the jason in string separated with "\n"

        try {
            URL url = new URL(apiUrl);
            httpCon = (HttpURLConnection) url.openConnection();

            if (httpCon.getResponseCode() != HttpURLConnection.HTTP_OK) { // check for connectivity with server
                return null;
            }
            input = new BufferedReader(new InputStreamReader(httpCon.getInputStream())); // pull all the json from the site
            String line;
            while ((line = input.readLine()) != null) {
                response.append(line + "\n");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (input != null) {
                try {
                    input.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (httpCon != null) {
                httpCon.disconnect();
            }
        }
        return response.toString();
    }
}

public ArrayList<Deal> processResponse(String response) {
    try {
        JSONObject responseObject = new JSONObject(response); // Creates a new JSONObject with name/value mappings from the JSON string.
        JSONArray results = responseObject.getJSONArray("movies"); // Returns the value mapped by name if it exists and is a JSONArray.
        deals = new ArrayList<Deal>();
        for (int i = 0; i < results.length(); i++) { // in this loop i copy the json array to movies arraylist in order to display  listView
            JSONObject jMovie = results.getJSONObject(i);
            int api_id = jMovie.getInt("id");
            String name = jMovie.getString("title");
            String content = jMovie.getString("synopsis");
            JSONObject posters = jMovie.getJSONObject("posters");
            String image_url = posters.getString("profile"); 
        }
    }catch (JSONException e) {
        e.printStackTrace();
    }
    return deals;
}

@Override
public void onStart() {
    super.onStart();

}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
    Intent intent = new Intent(getActivity().getBaseContext(), DealInformation.class);
    startActivity(intent);
    super.onListItemClick(l, v, position, id);
}
}

3 个答案:

答案 0 :(得分:1)

在他自己的档案中制作你的asynctask。

当你的asynctask完成后,实现自动调用的OnPostExecute。通过notifyDataSetChanged通知您的适配器:

    @Override
    protected void onPostExecute(List<NewItem> list) {
    Adapter.getListe().clear();     
    Adapter.getListe().addAll(list);
    Adapter.notifyDataSetChanged();
}

答案 1 :(得分:1)

谢谢你们,

我想发布我的回答。经过一些研究后,我决定选择AsyncTaskLoader。 这是我的代码

public class TabOurPicks extends ListFragment implements LoaderCallbacks<String[]>  {

// when activity loads- onActivityCreated() calls the initLoader() who activate onCreateLoader()
@Override
public void onActivityCreated(Bundle savedInstance) {
    super.onActivityCreated(savedInstance);
    setListAdapter(new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, new String[]{}));
    getLoaderManager().initLoader(0, null,this).forceLoad();
}

// onCreateLoader instantiate the asynctaskloaser who work in bg
@Override
public RSSLoader onCreateLoader(int arg0, Bundle arg1) {
    return new RSSLoader(getActivity());  // 
}

// after bg process invoke onLoadFinished() who work in ui thread
@Override
public void onLoadFinished(Loader<String[]> loader, String[] data) {
    setListAdapter(new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, data
) );

}

@Override
public void onLoaderReset(Loader<String[]> arg0) {
    // TODO Auto-generated method stub

}

这是加载器的内部类:

static public class RSSLoader extends AsyncTaskLoader<String[]>
{
    public RSSLoader(Context context) {
        super(context);
    }

    @Override
    public String[] loadInBackground() {
        String url = "http://api.rottentomatoes.com/api/public/v1.0/movies/770672122/similar.json?apikey=crhhxb4accwwa6cy6fxrm8vj&limit=1";
        String response = sendRequest(url);
        return processResponse(response);
    }


    private String sendRequest(String url) {
        BufferedReader input = null; // get the json
        HttpURLConnection httpCon = null; // the http connection object
        StringBuilder response = new StringBuilder(); // hold all the data from the jason in string separated with "\n"

        try {
            URL apiUrl = new URL(url);
            httpCon = (HttpURLConnection) apiUrl.openConnection();

            if (httpCon.getResponseCode() != HttpURLConnection.HTTP_OK) { // check for connectivity with server
                return null;
            }
            input = new BufferedReader(new InputStreamReader(httpCon.getInputStream())); // pull all the json from the site
            String line;
            while ((line = input.readLine()) != null) {
                response.append(line + "\n");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (input != null) {
                try {
                    input.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (httpCon != null) {
                httpCon.disconnect();
            }
        }
        return response.toString();
    }

    private String[] processResponse(String response) {
        String[] deals = null;
        try {
            JSONObject responseObject = new JSONObject(response); // Creates a new JSONObject with name/value mappings from the JSON string.
            JSONArray results = responseObject.getJSONArray("movies"); // Returns the value mapped by name if it exists and is a JSONArray.
            deals = new String[10];
            for (int i = 0; i < 9; i++) { // in this loop i copy the json array to movies arraylist in order to display  listView
                JSONObject jMovie = results.getJSONObject(i);
                String name = jMovie.getString("title");
                deals[i] = name;
            }
        }catch (JSONException e) {
            e.printStackTrace();
        }
        return deals;
    }
}

}

答案 2 :(得分:0)

asynctask是否有自己的文件并不重要。你只是不希望你的活动扩展asynctask,因为这会使你的活动异步 - 但由于java的双继承规则,这是不可能的。

根据应用程序的体系结构和编程风格,asyntask可以是活动中的内部类。在PostExecute方法上,确保已向适配器提供数据并将适配器设置为列表,然后运行notifyDataSetChanged()。

假设您的asynctask正在从缓存或网络加载数据,那么您的方法就是正确的。