2014-01-06 83 views
0

在我的android應用程序中,sd卡上有一個應用程序文件,在我們的服務器中也是如此,但服務器中的數據可能會更新。AsyncTask不能按預期工作

所以我做了一個活動來檢查最新的數據是否可用。

這是一個例子,只有一個按鈕「檢查」,當用戶點擊這個按鈕時,我會得到本地數據的信息,然後請求服務器檢查它是否可以被修改。由CheckTask完成,並在檢查過程中顯示進度對話框)。

然後,如果需要更新,我會提供一個對話框告訴用戶,他們可以選擇「立即下載」或「稍後下載」,如果他們選擇「立即下載」,將執行DownLoadTask,新的ProgressDialog將被創建以顯示下載的進度。

現在我遇到了一個問題:

一切運作良好,除非用戶點擊「立即下載」,然後取消下載。

然後當用戶點擊「檢查」按鈕時,CheckTask將無法​​正常工作。

這是代碼:

public class MyActivity extends Activity { 
    private DecimalFormat format = new DecimalFormat("0.#"); 

    private final int Dialog_Offline_Check_HaveUpdate = 13; 
    private final int Dialog_Offline_Download = 14; 


    private CheckTask mCheckTask; 
    private ProgressDialog mCheckProgressDialog; 

    private DownloadTask mDownloadTask; 
    private ProgressDialog mDownloadProgressDialog; 

    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
     this.setupView(); 
    } 


    private void setupView() { 
     mCheckProgressDialog = new ProgressDialog(this); 
     mCheckProgressDialog.setCanceledOnTouchOutside(false); 
     findViewById(R.id.check).setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View view) { 
       startCheckTask(); 
      } 
     }); 
    } 

    private void startCheckTask() { 
     if (mDownloadTask != null && !mDownloadTask.isCancelled()) { 
      showDialog(Dialog_Offline_Download); 
     } else { 
      //for debug 
      String data = String.format("{\"name\":\"%s\",\"size\":123455,\"lastModifiedTime\":\"2014-1-1\",\"hasUpdate\":false}", "Old Data"); 
      AppData appData = null; 
      try { 
       appData = buildMapData(data); 
      } catch (JSONException e) { 
       e.printStackTrace(); 
      } 
      if (mCheckTask != null) mCheckTask.cancel(true); 
      mCheckTask = new CheckTask(); 
      mCheckTask.execute(String.format("http://xxxx?t=%s", appData.lastModifiedTime)); 
     } 
    } 

    private void startDownLoadTask() { 
     if (mDownloadTask != null) { 
      mDownloadTask.cancel(true); 
     } 
     mDownloadTask = new DownloadTask(); 
     mDownloadTask.execute("https://dl.google.com/android/adt/adt-bundle-windows-x86-20131030.zip"); //for debug 
     showDialog(Dialog_Offline_Download); 
    } 


    @Override 
    protected Dialog onCreateDialog(int id) { 
     AlertDialog.Builder builder = new AlertDialog.Builder(this); 
     switch (id) { 
      case Dialog_Offline_Check_HaveUpdate: 
       builder.setTitle("Check Update").setPositiveButton("Download Now", new DialogInterface.OnClickListener() { 
        @Override 
        public void onClick(DialogInterface dialog, int id) { 
         dialog.dismiss(); 
         startDownLoadTask(); 
        } 
       }).setNegativeButton("Download Later", new DialogInterface.OnClickListener() { 
        public void onClick(DialogInterface dialog, int id) { 
         dialog.dismiss(); 
        } 
       }).setMessage("Latest Data avaiable!"); 
       return builder.create(); 
      case Dialog_Offline_Download: 
       mDownloadProgressDialog = new ProgressDialog(this); 
       mDownloadProgressDialog.setTitle("Download Latest Data"); 
       mDownloadProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); 
       mDownloadProgressDialog.setMax(100); 
       mDownloadProgressDialog.setButton(DialogInterface.BUTTON_POSITIVE, "Do it in Background", new DialogInterface.OnClickListener() { 
        public void onClick(DialogInterface dialog, int whichButton) { 
         dialog.dismiss(); 
        } 
       }); 
       mDownloadProgressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancel", new DialogInterface.OnClickListener() { 
        public void onClick(DialogInterface dialog, int whichButton) { 
         if (mDownloadTask != null) 
          mDownloadTask.cancel(true); 
        } 
       }); 
       mDownloadProgressDialog.setMessage(""); 
       return mDownloadProgressDialog; 
     } 
     return null; 
    } 

    @Override 
    protected void onPrepareDialog(int id, Dialog dialog, Bundle args) { 
     switch (id) { 
      case Dialog_Offline_Check_HaveUpdate: 
       String msgg; 
       AppData appData1 = (AppData) args.getSerializable("data"); 
       if (appData1 != null) { 
        msgg = String.format("%s\n%s: %s \n%s: %s\n%s: %s", "New Data Avaiable", 
          "Name", appData1.name, 
          "Size", makeFileSizeReadable(appData1.size), 
          "Last Update Time", appData1.lastModifiedTime); 
       } else { 
        msgg = ""; 
       } 
       ((AlertDialog) dialog).setMessage(msgg); 
       break; 
     } 
    } 

    private String makeFileSizeReadable(long size) { 
     double value; 
     String unit; 
     if (size < 1024) { 
      // < 1k 
      value = size; 
      unit = "Byte"; 
     } else if (size < 1024 * 1024) { 
      // 1k,1M 
      value = size/1024d; 
      unit = "Kb"; 
     } else { 
      value = size/1024d/1024d; 
      unit = "Mb"; 
     } 

     return String.format("%s %s", format.format(value), unit); 
    } 

    class CheckTask extends AsyncTask<String, Void, AppData> { 
     private String errorMsg; 
     private boolean cancel = false; 

     @Override 
     protected AppData doInBackground(String... urls) { 
      String url = urls[0]; 

      //for debug 
      String response = String.format("{\"name\":\"%s\",\"size\":222222,\"lastModifiedTime\":\"2014-1-5\",\"hasUpdate\":true}", "New Data"); 
      Log.d("map.setting", String.format("start parse result: [%s]", response)); 
      AppData md = null; 
      try { 
       md = buildMapData(response); 
      } catch (JSONException e) { 
       e.printStackTrace(); 
       Log.e("map.setting", "error when parse:" + e.getMessage()); 
      } 
      Log.d("map.setting", "get md:" + md); 
      return md; 
     } 

     @Override 
     protected void onPreExecute() { 
      mCheckProgressDialog.setMessage("Checking..."); 
      mCheckProgressDialog.show(); 
     } 

     @Override 
     protected void onPostExecute(AppData appData) { 
      mCheckProgressDialog.dismiss(); 
      if (appData == null) { 
       return; 
      } 

      if (appData.hasUpdate) { 
       Bundle bd = new Bundle(); 
       bd.putSerializable("data", appData); 
       showDialog(Dialog_Offline_Check_HaveUpdate, bd); 
      } else { 
       Toast.makeText(MyActivity.this, "Your data is the latest!", Toast.LENGTH_SHORT).show(); 
      } 
     } 
    } 

    private AppData buildMapData(String response) throws JSONException { 
     JSONObject root = new JSONObject(response); 
     String name = root.getString("name"); 
     long size = root.getLong("size"); 
     String lastModifiedTime = root.getString("lastModifiedTime"); 
     boolean hasUpdate = root.getBoolean("hasUpdate"); 

     AppData md = new AppData(); 
     md.name = name; 
     md.lastModifiedTime = lastModifiedTime; 
     md.size = size; 
     md.hasUpdate = hasUpdate; 
     return md; 
    } 


    class DownloadTask extends AsyncTask<String, Integer, String> { 

     @Override 
     protected String doInBackground(String... sUrl) { 
      try { 
       InputStream input = null; 
       OutputStream output = null; 
       HttpURLConnection connection = null; 
       try { 
        URL url = new URL(sUrl[0]); 
        connection = (HttpURLConnection) url.openConnection(); 
        connection.connect(); 

        // expect HTTP 200 OK, so we don't mistakenly save error report instead of the file 
        if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) { 
         return null; 
        } 
        int fileLength = connection.getContentLength(); 

        // download the file 
        input = connection.getInputStream(); 
        output = new FileOutputStream(Environment.getExternalStorageDirectory() + "/tmp.data", false); 

        byte data[] = new byte[4096]; 
        int total = 0; 
        int count; 
        while ((count = input.read(data)) != -1) { 
         total += count; 
         if (fileLength > 0) 
          publishProgress(total * 100/fileLength, total, fileLength); 
         output.write(data, 0, count); 
        } 
       } catch (Exception e) { 
        return null; 
       } finally { 
        try { 
         if (output != null) 
          output.close(); 
         if (input != null) 
          input.close(); 
        } catch (IOException ignored) { 
        } 

        if (connection != null) 
         connection.disconnect(); 
       } 
      } finally { 
//    wl.release(); 
      } 
      return null; 
     } 

     @Override 
     protected void onProgressUpdate(Integer... values) { 
      //progress current total 
      if (mDownloadProgressDialog != null) { 
       mDownloadProgressDialog.setProgress(values[0]); 
       String msg = String.format("Progress:%s/%s", makeFileSizeReadable(values[1]), makeFileSizeReadable(values[2])); 
       mDownloadProgressDialog.setMessage(msg); 
      } 
     } 

     @Override 
     protected void onPostExecute(String res) { 
      //map file downloaded replace the old file 
     } 

     @Override 
     protected void onCancelled() { 
      super.onCancelled(); 
     } 
    } 
} 

class AppData implements Serializable { 
    public String name; 
    public String lastModifiedTime; 
    public long size; 
    public boolean hasUpdate; 
} 

任何人都可以找到是什麼問題?

回答

0

是否在HONEYCOMB之後遇到AsynTask的bug?

執行順序 第一次引入時,AsyncTasks在單個後臺線程上被串行執行。從DONUT開始,將其更改爲允許多個任務並行操作的線程池。從HONEYCOMB開始,任務在單個線程上執行,以避免並行執行導致的常見應用程序錯誤。

如果您真的想要並行執行,可以使用THREAD_POOL_EXECUTOR調用executeOnExecutor(java.util.concurrent.Executor,Object [])。

在我們的項目中,我們使用AsynTask這樣的:

public void executeParallelly(Params... params) { 
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { 
     task.execute(params); 
    } else { 
     task.executeOnExecutor(AsynTask.THREAD_POOL_EXECUTOR, params); 
    } 
} 
+0

但我不使用'平行execution'不是嗎? – hguser