0

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

这是代码:

公共类 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();
    }
}
4

1 回答 1

1

Activity被销毁时,它失去了对 的引用AsyncTask,因为当AsyncTask它被创建时,它被传递给创建它的实例的引用Activity。当实例死亡时,对 Activity 的引用变得无用。

更好的方法是将AsyncTask放入 aService中,设置Service并设置AsyncTask运行Service并将您绑定ActivityService.

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

这种方式的另一个好处是你的Service可以在通知栏中放一个通知图标,大大降低了它被系统杀死的机会,用户可以一目了然地查看进度,甚至可以在进程完成时收到通知.

允许 AsyncTask 与其所有者(即 Activity)分离并相信它会完成它所做的事情是一个非常糟糕的主意,并且可能会产生一些意想不到的结果,导致潜在的内存泄漏等。

于 2012-05-27T22:26:42.857 回答