0

私は現在、バックグラウンドでAsyncTaskを実行し、プログレスバーでUIを更新するアプリに取り組んでいます。プログレスバーはアプリの実行中は正常に機能しますが、ユーザーがアプリを終了して再入力すると、AsyncTaskはバックグラウンドで実行されたままになりますが、プログレスバーは更新されません。これは、AsyncTaskがアクティビティから切り離されたかのようです。AsyncTasksに関連する一般的なルールなど、これを引き起こしている可能性のあるアイデアを誰かが持っていますか?必要に応じてコードを提供することもできますが、かなり長いので、どの部分を見る必要があるか教えてください。また、AsyncTaskが完了することにも注意する必要があります。これは、終了時にデータベースをサーバーにアップロードするためです。

コードは次のとおりです。

public class BackgroundAsyncTask extends 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

より良いアプローチは、 を に入れ、AsyncTaskServiceセットアップしServiceAsyncTask実行中を に設定して、ServiceにバインドするActivityことServiceです。

次に、 の新しいインスタンスActivityが作成されると (つまり、ユーザーがアプリを再起動したとき)、Service既に実行されている同じインスタンスにバインドし、自身への参照を渡して進行状況情報を受け取ることができます。

このアプローチのもう1つの利点は、サービスが通知バーに通知アイコンを配置できることです。これにより、システムによって強制終了される可能性が大幅に減少し、ユーザーは進行状況を一目で確認でき、プロセスが完了したときに通知を受けることさえできます.

AsyncTask をその所有者 (アクティビティ) から切り離すことを許可し、その実行を完了することを信頼するのはかなり悪い考えであり、おそらく予期しない結果が生じたり、潜在的なメモリ リークなどにつながる可能性があります。

于 2012-05-27T22:26:42.857 に答える