【问题标题】:Executing Async tasks in fragments在片段中执行异步任务
【发布时间】:2014-02-08 18:28:44
【问题描述】:

在将我的活动转换为片段后,我试图在片段中执行异步任务。当我从活动中调用我的异步任务时,我必须将“this”传递给它,以允许异步任务在接收到信息后更改文本和内容。我对如何使用片段来完成这一切感到有些困惑。这是我到目前为止得到的:

我执行异步任务:

new GetYourTopTasteBeers(this).execute(url);

异步任务的代码是:

public class GetYourTopTasteBeers extends AsyncTask<String, Void, String> {

    Context c;
    private ProgressDialog Dialog;

    public GetYourTopTasteBeers (Context context)
    {
        c = context;
        Dialog = new ProgressDialog(c);
    }

    @Override
    protected String doInBackground(String... arg0) {
        // TODO Auto-generated method stub
        return readJSONFeed(arg0[0]);
    }

    protected void onPreExecute() {
        Dialog.setMessage("Getting beers");

        Dialog.setTitle("Loading");
        Dialog.setCancelable(false);
        Dialog.show();
    }

    protected void onPostExecute(String result){
        //decode json here
        try{
            JSONArray jsonArray = new JSONArray(result);


            //acces listview
            ListView lv = (ListView) ((Activity) c).findViewById(R.id.topTasteBeers);

            //make array list for beer
            final List<ShortBeerInfo> tasteList = new ArrayList<ShortBeerInfo>();



            for(int i = 0; i < jsonArray.length(); i++) {

                String beer = jsonArray.getJSONObject(i).getString("beer");
                String rate = jsonArray.getJSONObject(i).getString("rate");
                String beerID = jsonArray.getJSONObject(i).getString("id");
                String breweryID = jsonArray.getJSONObject(i).getString("breweryID");


                int count = i + 1;

                beer = count + ". " + beer;


                //create object
                ShortBeerInfo tempTaste = new ShortBeerInfo(beer, rate, beerID , breweryID);

                //add to arraylist
                tasteList.add(tempTaste);


                //add items to listview
                ShortBeerInfoAdapter adapter1 = new ShortBeerInfoAdapter(c ,R.layout.brewer_stats_listview, tasteList);
                lv.setAdapter(adapter1);

                //set up clicks
                lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                    @Override
                    public void onItemClick(AdapterView<?> arg0, View arg1,
                                            int arg2, long arg3) {
                        ShortBeerInfo o=(ShortBeerInfo)arg0.getItemAtPosition(arg2);

                        String tempID = o.id;
                        String tempBrewID = o.brewery;

                        Toast toast = Toast.makeText(c, tempID, Toast.LENGTH_SHORT);
                        toast.show();

                        //todo: change fragment to beer page

                        Intent myIntent = new Intent(c, BeerPage2.class);
                        myIntent.putExtra("id", tempID);
                        myIntent.putExtra("breweryID", tempBrewID);
                        c.startActivity(myIntent);


                    }
                });




            }

        }
        catch(Exception e){

        }

        Dialog.dismiss();

    }

    public String readJSONFeed(String URL) {
        StringBuilder stringBuilder = new StringBuilder();
        HttpClient httpClient = new DefaultHttpClient();
        HttpGet httpGet = new HttpGet(URL);
        try {
            HttpResponse response = httpClient.execute(httpGet);
            StatusLine statusLine = response.getStatusLine();
            int statusCode = statusLine.getStatusCode();
            if (statusCode == 200) {
                HttpEntity entity = response.getEntity();
                InputStream inputStream = entity.getContent();
                BufferedReader reader = new BufferedReader(
                        new InputStreamReader(inputStream));
                String line;
                while ((line = reader.readLine()) != null) {
                    stringBuilder.append(line);
                }
                inputStream.close();
            } else {
                Log.d("JSON", "Failed to download file");
            }
        } catch (Exception e) {
            Log.d("readJSONFeed", e.getLocalizedMessage());
        }
        return stringBuilder.toString();
    }

}

我的问题是我无法从片段中传递“this”...

额外问题:

正如您所见,我还没有完成片段代码的转换。我需要更改它以加载片段而不是更改活动:

//todo: change fragment to beer page
                        Intent myIntent = new Intent(c, BeerPage2.class);
                        myIntent.putExtra("id", tempID);
                        myIntent.putExtra("breweryID", tempBrewID);
                        c.startActivity(myIntent);

如何在片段之间传递值,就像我在上面代码中的活动之间所做的那样?

【问题讨论】:

    标签: android asynchronous android-fragments android-asynctask


    【解决方案1】:

    由于Fragments 不承认this,您可以改为调用getActivity(),它将提供执行AsyncTask 所需的上下文。

    但要小心,因为在Fragment 中运行AsyncTask 可能会导致将结果返回给调用者Activity,在您的AsyncTask 结束其进程时该结果已被销毁。有必要采取额外的预防措施,并始终检查Fragment 是否尚未被销毁。这可以在您的Fragment 中使用this.isAdded() 来完成。

    一个好的做法是在onStop()onPause() 方法中取消您的AsyncTask。如果Fragment 不再处于活动状态,这将使onPostExecute() 不执行代码(getActivity() 将返回 null)。

    【讨论】:

    • onStop() 中取消AsyncTask 确实是一个好习惯。但不要在onPause() 中这样做。 onPause()执行后Activity依然存在,无需取消。
    • 如果有任何风险,应该停止它会在该暂停内更新。但是,即使它已暂停(例如,TCP 套接字),您也可能需要它运行
    【解决方案2】:

    您不能传递this,因为在这种情况下this 引用到您的片段,它不会扩展Context。但是您需要Context(您的GetYourTopTasteBeersContext 作为参数):

    public GetYourTopTasteBeers (Context context)
    

    相反,像这样传递您的Activity

    new GetYourTopTasteBeers(getActivity()).execute(url);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多