2012-05-27 12 views
0

我目前正在研究在後臺運行AsyncTask並使用進度條更新UI的應用程序。進度條在應用程序運行時工作正常,但是,當用戶退出應用程序並重新進入時,AsyncTask仍在後臺運行,但進度欄不會更新。就好像AsyncTask已經脫離了活動。有沒有人有任何想法可能會導致這種情況,如涉及AsyncTasks的一般規則。如果需要,我可以提供代碼,但它相當長,所以請讓我知道您需要查看哪些部分。我還應該注意到AsyncTask完成了,我可以告訴它,因爲它完成時會將數據庫上傳到服務器。退出並重新輸入應用程序後從AsyncTask更新UI

下面是代碼:

公共類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(); 
    } 
} 
+0

粘貼asynctask類代碼,以及你在哪裏執行它。 –

+0

因此,當進展爲例如80%和用戶存在的應用程序,並重新輸入,所以你想進度條繼續從80%更新? – Sajmon

+0

是的,Sajmon是正確的。它不會從它離開的地方開始。 – johns4ta

回答

1

Activity被破壞,它就失去了參考AsyncTask,爲創建AsyncTask當它到實例創建它的Activity的引用傳遞。當實例死亡時,對Activity的引用變得毫無用處。

一個更好的辦法是把AsyncTaskService,成立了Service並設置AsyncTaskService運行,並綁定您ActivityService

然後,當創建一個Activity的新實例(即用戶重新輸入應用程序時),它可以綁定到已在運行的同一個Service實例,並傳入對其自身的引用以接收進度信息。

這種方法的另一個優點是您的服務可以在通知欄中放置通知圖標,這大大降低了系統被殺死的機率,用戶可以一目瞭然地查看進度,甚至可以通知何時該過程完成。

允許將AsyncTask從它的所有者(是Activity)中分離出來並相信它會完成它所做的是一個非常糟糕的主意,並且可能會有一些意想不到的結果,導致潛在的內存泄漏等。

相關問題