【问题标题】:Can I use AsyncTask inside ListFragment? or should I use AsyncTaskLoader?我可以在 ListFragment 中使用 AsyncTask 吗?还是我应该使用 AsyncTaskLoader?
【发布时间】:2013-03-13 13:38:34
【问题描述】:

我尝试了下面的代码,还尝试了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);
}
}

【问题讨论】:

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


    【解决方案1】:

    在他自己的文件中创建你的异步任务。

    当你的异步任务完成后,实现自动调用的 OnPostExecute。通过这样的 notifyDataSetChanged 通知您的适配器:

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

    【讨论】:

      【解决方案2】:

      谢谢你们,

      我想发布我的答案。经过一些研究,我决定使用 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;
          }
      }
      
      }
      

      【讨论】:

        【解决方案3】:

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

        根据您应用的架构和您的编程风格,asyntask 可以是 Activity 中的内部类。在 PostExecute 方法上确保您已向适配器提供数据并且适配器已设置为列表,然后只需运行 notifyDataSetChanged()。

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-02-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-02-25
          相关资源
          最近更新 更多