AsyncTask无法按预期工作

时间:2014-01-06 02:35:38

标签: android

在我的Android应用程序中,sd卡上有一个app文件,在我们的服务器上也是如此,但服务器中的数据可能会更新。

所以我做了一个活动来检查最新的数据是否可用。

这是一个例子,只有一个按钮" Check",当用户点击此按钮时,我将获取本地数据的信息,然后请求服务器检查它是否可以udpated。(这是由CheckTask完成的,在检查过程中会显示一个进度对话框。

然后,如果需要更新,我将提供一个对话框告诉用户,他们可以选择&#34;立即下载&#34;或者&#34;稍后下载&#34;,如果他们选择&#34;立即下载&#34;,将执行DownLoadTask,并将创建一个新的ProgressDialog以显示下载的进度。< / p>

现在我遇到了一个问题:

除非用户点击&#34;立即下载&#34;否则一切正常然后取消下载。

然后当用户点击&#34;检查&#34;按钮,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;
}

任何人都可以找到问题所在?

1 个答案:

答案 0 :(得分:0)

你在HONEYCOMB之后遇到AsynTask的错误吗?

执行顺序 首次引入时,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);
    }
}