Search code examples
androidandroid-fragmentsandroid-asynctaskandroid-tabhost

How to cancel the async task with tab host


I am currently working with the tab host and fragment. Currently I set fragment a to download json A and fragment B to download json B , the problem is when I switch fragment, the fragment A onPostExecute function will fall into the fragment B one , is there any way to fix this? Thanks

Tab host:

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);

The async task

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;
            }
        }
    }
}

Solution

  • I used it in my app this way which works for me and answer is a bit similar to another answer but few additions and more detail. Hope it help you too.

    NOTE: This is just a idea, u need to try, it may vary as per your app architect.

    At your activity make the task object global [make sure set task obj null once task is finish]

     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);  
       }
      }
    

    At the Async class side....[make sure u take care null result @ 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). 
      }
     }