退出并重新进入应用程序后,从AsyncTask更新UI

时间:2012-05-27 20:06:38

标签: android

我目前正在开发一个在后台运行AsyncTask的应用程序,并使用进度条更新UI。应用程序运行时,进度条工作正常,但是,当用户退出应用程序并重新进入时,AsyncTask仍在后台运行,但进度条不会更新。这就好像AsyncTask已从活动中分离出来一样。有没有人有任何想法可能导致这种情况,如AsyncTasks涉及的一般规则。如果需要,我可以提供代码,但它相当冗长,所以让我知道你需要看到哪些部分。我还应该注意到AsyncTask确实完成了,我可以告诉它,因为它在完成后将数据库上传到服务器。

以下是代码:

public class BackgroundAsyncTask扩展AsyncTask {         int myProgress;

    @Override
    protected void onPostExecute(Void result) {
        ((TextView) findViewById(R.id.tv1)).setText("");
        Cursor cur = sql3.query("videohashes", null, null, null, null,
                null, null);
        cur.moveToFirst();
        while (!cur.isAfterLast()) {

            Cursor curFrame = sql3.query("table_" + cur.getString(2), null,
                    null, null, null, null, null);
            curFrame.moveToFirst();

            ((TextView) findViewById(R.id.tv1)).append("\nPath: "
                    + cur.getString(1) + "\nHash: " + cur.getString(2)
                    + "\nDate:" + cur.getString(3) + "\nSize: "
                    + cur.getString(4) + " bytes\nResolution"
                    + cur.getString(5) + "\nFormat: " + cur.getString(6)
                    + "\nCodec: " + cur.getString(7) + "\nFPS: "
                    + cur.getString(8) + "\n\nFirst Frame Info:\nType: "
                    + curFrame.getString(1) + "\ncp_num: "
                    + curFrame.getString(2) + "\ndp_num: "
                    + curFrame.getString(3) + "\npts: "
                    + curFrame.getString(4) + "\nqstride: "
                    + curFrame.getString(5) + "\nsize: "
                    + curFrame.getString(6) + "\nqp_stddev: "
                    + curFrame.getString(7) + "\ncount: "
                    + curFrame.getString(8) + "\nqp_avg: "
                    + curFrame.getString(9) + "\n\n");

            cur.moveToNext();
        }
        cur.close();
        ((Button) findViewById(R.id.btnSend)).setEnabled(true);
        ((Button) findViewById(R.id.btnStart)).setEnabled(true);
        sql3.close();
        sharedPreferences.edit().putString("lastVideoInfo", ((TextView) findViewById(R.id.tv1)).getText().toString()).commit();
        sharedPreferences.edit().putBoolean("asyncTaskRunning", false).commit();
        dateNow = new Date();
        super.onPostExecute(result);
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        totProgress = 0;
        currVid = 0;
        curProgress = 0;
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        progress.setProgress(values[0]);
    }

    @Override
    protected Void doInBackground(Void... arg0) {

        // Calculate total size of all files
        for (String path : myFiles) {
            totProgress += getFileSize(path);
        }

        progress.setMax(totProgress);
        String strDB3File = getFilesDir().getPath() + "/VideoHashes.db3";
        sql3 = SQLiteDatabase.openDatabase(strDB3File, null,
                SQLiteDatabase.CREATE_IF_NECESSARY);

        try {
            String mysql = "CREATE TABLE IF NOT EXISTS videohashes (id INTEGER  NOT NULL PRIMARY KEY AUTOINCREMENT, path TEXT NOT NULL, hash TEXT NOT NULL, date TEXT NOT NULL, size INTEGER, resolution TEXT NOT NULL, codec TEXT NOT NULL, format TEXT NOT NULL, fps TEXT NOT NULL)";
            sql3.execSQL(mysql);
        } catch (SQLiteException e) {
            // TODO: handle exception
        }

        for (String path : myFiles) {
            try {

                String hash = getMD5Checksum(path);

                Cursor curFrame = sql3.query("videohashes",
                        new String[] { "hash" }, "hash=?",
                        new String[] { hash }, null, null, null);

                if (!curFrame.moveToFirst()) {
                    ContentValues myInsertData = new ContentValues();
                    myInsertData.put("path", path);
                    myInsertData.put("hash", hash);
                    Date date = new Date();
                    myInsertData.put("date", dateFormat.format(date));
                    myInsertData.put("size", getFileSize(path));

                    naInit(path);
                    Log.i("VPMA", "After naInit");
                    int[] prVideoRes = naGetVideoResolution();
                    myInsertData.put("resolution", prVideoRes[0] + "x"
                            + prVideoRes[1]);
                    String prVideoCodecName = naGetVideoCodecName();
                    myInsertData.put("codec", prVideoCodecName);
                    String prVideoFormatName = naGetVideoFormatName();
                    myInsertData.put("format", prVideoFormatName);
                    double prFps = naGetVideoFPS();
                    Log.i("VPMA", "fps: " + prFps);
                    myInsertData.put("fps", prFps);
                    Object[] prObjArray = naGetArray();
                    Log.i("VPMA", (String) prObjArray[0]);
                    String[] prStrArray = Arrays.copyOf(prObjArray,
                            prObjArray.length, String[].class);
                    Log.i("VPMA", "before frames");
                    try {
                        String mysql = "CREATE TABLE table_"
                                + hash
                                + " (id INTEGER  NOT  NULL PRIMARY KEY AUTOINCREMENT, type TEXT NOT NULL, cp_num TEXT NOT NULL, dp_num TEXT NOT NULL, pts TEXT NOT NULL, qstride TEXT NOT NULL, size TEXT NOT NULL, qp_stddev TEXT NOT NULL, count TEXT NOT NULL, qp_avg TEXT NOT NULL)";
                        sql3.execSQL(mysql);
                    } catch (SQLiteException e) {
                        // TODO: handle exception
                    }
                    for (String str : prStrArray) {
                        ContentValues myFrameInsertData = new ContentValues();
                        String[] strArr = str.split(",");
                        if (strArr.length == 9) {
                            String stddev = "", strCount = "", strQp_avg = "";
                            double sd, qp_avg, count = 0, sum = 0, sqrSum = 0;
                            try {
                                count = Integer.parseInt(strArr[6].trim());
                                sum = Integer.parseInt(strArr[7].trim());
                                sqrSum = Integer.parseInt(strArr[8].trim());

                                //sd = (sum * sum / count);
                                sd = (sqrSum - (sum*sum/count))/(count-1);//(sqrSum - sd) / (count - 1);
                                stddev = String.valueOf(sd);
                                qp_avg = sum / count;
                                strCount = String.valueOf(count);
                                strQp_avg = String.valueOf(qp_avg);
                            } catch (Exception e) {
                                Log.i("Error: ", "error converting values");
                            }
                            //Log.i("Java Code: ", "Sum: " + sum + " SqrSum: " + sqrSum + " Count: " + count);
                            //Log.i("Java Code: ", "StdDev: " + stddev + " qp_avg: " + strQp_avg);
                            myFrameInsertData.put("type", strArr[0]);
                            myFrameInsertData.put("cp_num", strArr[1]);
                            myFrameInsertData.put("dp_num", strArr[2]);
                            myFrameInsertData.put("pts", strArr[3]);
                            myFrameInsertData.put("qstride", strArr[4]);
                            myFrameInsertData.put("size", strArr[5]);
                            myFrameInsertData.put("qp_stddev", stddev);
                            myFrameInsertData.put("count", strCount);
                            myFrameInsertData.put("qp_avg", strQp_avg);

                            sql3.insert("table_" + hash, null,
                                    myFrameInsertData);
                        }
                    }
                    sql3.insert("videohashes", null, myInsertData);
                    naClose();
                }
                curFrame.close();
                currVid++;
                curProgress += getFileSize(path);
                publishProgress(curProgress);
                Log.i("Progress", "CurrVid:" + currVid + "  Max:"
                        + progress.getMax());
            } catch (Exception e) {
                Log.i("File", "File not Found");
            }
        }
        return null;
    }
}
    }
    if (sharedPreferences.getBoolean("asyncTaskRunning", false) == false)
    {
        ((Button) findViewById(R.id.btnStart)).setEnabled(false);
        progress = (ProgressBar) findViewById(R.id.progressBar1);
        text = (TextView) findViewById(R.id.tv1);
        if (sharedPreferences.contains("lastVideoInfo"))
        {
            text.setText("Last Video Information Parsed " + "(" + dateFormat.format(dateNow) + "):\n\n" +  sharedPreferences.getString("lastVideoInfo", ""));
            ((Button) findViewById(R.id.btnSend)).setEnabled(true);
        }
        else
        {
            text.setText("");
            ((Button) findViewById(R.id.btnSend)).setEnabled(false);
        }
        progress.setProgress(0);

        myFiles = new ArrayList<String>();
        new StartAsyncTask().execute();
    }
}

1 个答案:

答案 0 :(得分:1)

Activity被销毁时,它会丢失对AsyncTask的引用,就像创建AsyncTask时一样,它会在对实例Activity的>。当实例终止时,对Activity的引用变得无用。

更好的方法是将AsyncTask放入Service,设置Service并将AsyncTask设置为Service并绑定您的Activity Service Activity

然后,当创建Service的新实例时(即当用户重新进入应用程序时),它可以绑定到已经运行的同一个{{1}}实例,并传入一个引用它自己接收进度信息。

这种方法的另一个优点是您的服务可以在通知栏中放置一个通知图标,这大大降低了被系统杀死的可能性,用户可以一目了然地查看进度,甚至可以通知过程完成。

允许从其所有者(是活动)中删除AsyncTask,并相信它将完成它所做的事情是一个非常糟糕的主意,并且可能会有一些意想不到的结果,导致潜在的内存泄漏等。