在我的android應用程序中,在某個活動中,我需要創建視圖的屏幕截圖而不實際顯示它們。我通過誇大觀點並將它們保存爲位圖來成功實現這一目標。 但是在某些情況下,這些位圖的數量足夠大,需要花費很多時間來創建它們。因此,手機上的用戶界面變得無法響應。有什麼辦法可以在後臺完成整個過程嗎?我已經嘗試過在異步任務中實現它,但這不起作用,因爲它不允許在異步任務中對視圖進行充氣。從背景中創建位圖
任何建議,非常感謝。
在我的android應用程序中,在某個活動中,我需要創建視圖的屏幕截圖而不實際顯示它們。我通過誇大觀點並將它們保存爲位圖來成功實現這一目標。 但是在某些情況下,這些位圖的數量足夠大,需要花費很多時間來創建它們。因此,手機上的用戶界面變得無法響應。有什麼辦法可以在後臺完成整個過程嗎?我已經嘗試過在異步任務中實現它,但這不起作用,因爲它不允許在異步任務中對視圖進行充氣。從背景中創建位圖
任何建議,非常感謝。
AsyncTask doBackground方法在另一個線程上工作,這就是您無法膨脹視圖的原因。
首先是否有一個或多個佈局。如果你有很多,然後嘗試下面。
我還沒有測試過這個。只是給你一個樣品。
public class Task extends AsyncTask<Void, Integer, Void>
{
private ArrayList<Integer> layoutIds;
private View currentView;
private LayoutInflater inflater;
private Object lock = new Object();
public Task(Context context) {
super();
inflater = LayoutInflater.from(context);
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected Void doInBackground(Void... params) {
Bitmap temp;
for (int i = 0; i < layoutIds.size(); i++) {
temp = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
Canvas canvas = new Canvas(temp);
synchronized (lock) {
publishProgress(i);
try {
// Wait for the UI Thread to inflate the layout.
lock.wait();
}
catch (InterruptedException e) {
}
}
currentView.draw(canvas);
// Now save this bitmap
try {
FileOutputStream stream = new FileOutputStream(new File(Environment.getExternalStorageDirectory(), "File_" + i + ".png"));
temp.compress(Bitmap.CompressFormat.PNG, 100, stream);
stream.flush();
stream.close();
} catch (Exception e) {
}
finally
{
if(temp != null)
{
temp.recycle();
temp = null;
}
}
}
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {
synchronized (lock) {
currentView = inflater.inflate(layoutIds.get(values[0]), null);
// Notify async thread that inflate is done.
lock.notifyAll();
}
}
}
EDITED
在這裏,我們有兩個線程之一的AsyncTask這是一個線程池,另一個是UI線程。
用synchronized塊,我們可以確保只有一個線程可以,只要它是不是在睡覺或等待另一個線程使用對象鎖定。
因此,如果一個線程執行內部同步塊,然後將開始監視對象,並確保沒有其他線程裏面也有該對象的同步塊將被執行。即只要活動線程進入睡眠狀態或在同步塊內完成其執行,另一個線程就必須等待。
有關詳細說明,請參見this
在這裏,我們使用的同步塊等待UI線程來完成。
所以它執行lock.wait()時,AsyncThread將等到另一個線程調用同一個對象的通知。當調用lock.notifyAll()時,所有正在等待的線程(AsyncThread)都將被恢復。
AsyncTask
分爲onPreExecute()
,onProgressUpdate()
和onPostExecute()
,全部發生在主UI線程中,允許您膨脹視圖。只有doInBackground()
是事實上發生在另一個線程中的地方。如果你可以用這種方法進行計算,只需要膨脹onProgressUpdate()
或onPostExecute()
它可能會有幫助。 另外,如果你可以給我們你的代碼,它可能會幫助我們找到一種方法來提高CPU的效率。
總之,Android將嘗試強制關閉應用,如果UI線程不響應時間超過5秒,那裏有沒有太大怎麼辦呢(據我所知)。
Aviel,我已經嘗試在'onProgressUpdate'和'onPostExecute'中進行膨脹,正如你正確地提到Android試圖在5秒後強制關閉應用程序。 – Anuj 2013-05-13 17:08:48
這些意見已經在背景中誇大了嗎?如果是這樣,你可能只是得到繪圖緩存 – Guardanis 2013-05-13 13:15:42