如何使用选项卡主机取消异步任务

时间:2014-01-31 18:32:35

标签: android android-fragments android-asynctask android-tabhost

我目前正在使用标签主机和片段。目前我设置片段a下载json A和片段B下载json B,问题是当我切换片段时,片段A onPostExecute函数将落入片段B中,有没有办法解决这个问题? 感谢

标签主持人:

tabHost = (FragmentTabHost) findViewById(R.id.tabhost);
        tabHost.setup(this, getSupportFragmentManager(), R.id.tabcontent);
        tabHost.addTab(
                tabHost.newTabSpec("Home").setIndicator("",
                        res.getDrawable(R.drawable.btn_about)), Home.class,
                null);
        tabHost.addTab(
                tabHost.newTabSpec("About").setIndicator("",
                        res.getDrawable(R.drawable.btn_about)), About.class,
                null);

异步任务

public class JSONReader {
    public static final String TAG = "JSONReader";
    public ArrayList<Record> records;
    public Record myRecordObj;
    public ArrayList<GalleryImage> images;
    public String url;
    public int failCount = 0; // retry twice
    public Context ctx;
    public String readCase;

    public JSONReader(String _url, Context _ctx , String _readCase) {
        url = _url;
        ctx = _ctx;
        readCase = _readCase;
    }

    public void getJSON() {
        new JSONDownload().execute(url);
    }

    private class JSONDownload extends AsyncTask<String, Void, JSONObject> {
        // TODO Auto-generated method stub
        StringBuilder builder = new StringBuilder();
        String temp = "";
        String json = ""; // json content
        InputStream input = null;
        OutputStream output = null;
        HttpURLConnection connection = null;

        @Override
        protected JSONObject doInBackground(String... params) {
            // TODO Auto-generated method stub

            try {
                Log.d(TAG, "Start reading: " + url);
                URL url = new URL(params[0]);
                connection = (HttpURLConnection) url.openConnection();
                connection.connect();

                if (connection.getResponseCode() != HttpURLConnection.HTTP_OK)
                    return null;
                // return "Server returned HTTP " + connection.getResponseCode()
                // + " " + connection.getResponseMessage();

                input = connection.getInputStream();

                BufferedReader reader = new BufferedReader(
                        new InputStreamReader(input));

                while ((temp = reader.readLine()) != null) {
                    builder.append(temp);
                }

                json = builder.toString();
            } catch (Exception e) {
                return null;
            } finally {
                try {
                    if (input != null)
                        input.close();
                    if (output != null)
                        output.close();
                } catch (IOException ignored) {
                }
                if (connection != null)
                    connection.disconnect();
            }

            try {
                return new JSONObject(json);
            } catch (JSONException e) {
                e.printStackTrace();
                return null;
            }
        }

        @Override
        protected void onPostExecute(JSONObject result) {
            // TODO Auto-generated method stub
            super.onPostExecute(result);
            onJSONDownloaded(result);
        }

    }

    public void onJSONDownloaded(JSONObject result) {
        // TODO Auto-generated method stub
        if (result != null) {

            failCount = 0;

            if (readCase.equals("leaderBoard")){
                records = new ArrayList<Record>();

                try {
                    JSONObject myRecord = result.getJSONObject("myRecord");

                    if (myRecord != null) {
                        myRecordObj = new Record(myRecord.getString("pic"),myRecord.getString("name"),myRecord.getString("score"));
                    }

                    JSONArray topRecords = result.getJSONArray("topRecord");

                    for (int i = 0; i < topRecords.length(); i++) {
                        JSONObject topRecord = topRecords.getJSONObject(i);
                        String topName = topRecord.getString("name");
                        String topPic = topRecord.getString("pic");
                        String topScore = topRecord.getString("score");
                        records.add(new Record(topPic, topName, topScore));
                    }

                } catch (JSONException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

                ((LeaderBoardDetail)ctx).setData(records,myRecordObj);
            } else if (readCase.equals("galleryList")){
                images = new ArrayList<GalleryImage>();

                try {
                    JSONArray imageList = result.getJSONArray("images");
                    for (int i = 0; i < imageList.length(); i++) {
                        JSONObject image = imageList.getJSONObject(i);
                        images.add(new GalleryImage(image.getString("url"),image.getString("thumbUrl"),image.getString("category"),image.getString("userPic"),image.getString("name")));
                    }
                } catch (JSONException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

                //exception
                if (((FragmentActivity) ctx).getSupportFragmentManager().findFragmentById(R.id.tabcontent).getTag().equals("Gallery")) {
                    PhotoGallery galleryFragment = (PhotoGallery) ((FragmentActivity) ctx).getSupportFragmentManager().findFragmentById(R.id.tabcontent);
                    galleryFragment.setData(images);
                }

            }

        } else {
            if (failCount <= 1) { // check global_conf twice if fail
                failCount++;
                Log.d(TAG, "No of retry" + failCount);
                new JSONDownload().execute(url); // Retry download json
            } else {
                failCount = 0;
            }
        }
    }
}

3 个答案:

答案 0 :(得分:1)

使用全局异步任务变量

LongOperation LongOperationOdeme = new LongOperation();

并设置:

LongOperationOdeme.cancel(true);

这将停止当时正在运行的任何异步任务,这是后退按钮的作用

答案 1 :(得分:1)

如果你不是在寻找一个最简单的答案,而是为了更有趣和更优雅,可以看一下this article,特别是如果你发现函数式编程很有趣。

它比它看起来容易,在本文之前我对FP几乎不熟悉,但它涵盖了与Android中的AsyncTask和异步性相关的常见问题,因此我得到了要点并考虑使用{{1}而不是Observables在未来的项目中自己。它是RxJava,它可以优雅地解决您的问题:“fromFragment调用转换给定的源可观察对象,只有当事件仍处于活动状态且附加到其主机活动时才会将事件发送到该片段。” / p>

该文章还有一个引用:“如果用户决定退出触发任务的Activity,并且我们正在坚持过时的参考,那会怎样。这不仅会造成大量的内存泄漏,而且也会毫无价值因为同时它已经从应用程序窗口中分离出来了。everyone is well aware of。“

的问题

答案 2 :(得分:1)

我在我的应用程序中使用它,这对我有用,答案有点类似于另一个答案,但很少添加和更多细节。希望它也能帮助你。

注意:这只是一个想法,您需要尝试,它可能会因您的应用程序架构师而异。

在您的活动中,将任务对象设为全局[确保在任务完成后将任务obj设置为null]

 JSDownload js = null;

public void getJSON() {

 if(js != null && js.getStatus() == AsyncTask.Status.RUNNING) 
 { 
   js.cancel(true);  
   if(js.isCancelled())
   {
     js = new JSONDownload();
     js.execute(url);
   }
   else
   {

     js = new JSONDownload();
     js.execute(url);  
   }
  }

在Async类的一侧.... [确保你注意null结果@ onpostExcute]

class JSONDownload extends AsyncTask<String, Void, JSONObject> 
{
    protected JSONObject doInBackground(String... params) {
        // TODO Auto-generated method stub
        try {

            if(!this.isCancelled())
         {
               //make http connection ..
             URL url = new URL(params[0]);
            connection = (HttpURLConnection) url.openConnection();
            connection.connect();


           //as we are in steps in bg check iscancel .. again 
          //if its a loop here we call break; and return null once only..
          if(this.isCancelled())
                   return null;
         // connection status check and get buffer etc .. code here

            if(this.isCancelled()) 
              return null;

         //read data 
        return data;
      }

     }  catch (Exception e) {
            return null;
        } 
   }


  @Override
   protected void onCancelled(){
 // If you write your own implementation, do not call super.onCancelled(result). 
  }
 }