2014-01-06 84 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