在我的Android应用程序中,对于某个活动,我需要创建视图的屏幕截图而不实际显示它们。我通过膨胀视图并将其保存为位图来成功实现这一目标。 但在某些情况下,这些位图的数量足够大,创建它们需要花费大量时间。因此,手机上的UI变得无响应。有什么方法可以在后台完成整个过程吗?我已经尝试在异步任务中实现它,但这不起作用,因为它不允许在异步任务中膨胀视图。
非常感谢任何建议。
答案 0 :(得分:2)
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
在这里,我们使用synchronize块等待UI线程完成。
因此,当它执行lock.wait()时,AsyncThread将等到另一个线程调用同一对象上的notify。当调用lock.notifyAll()时,所有正在等待的线程(AsyncThread)将被恢复。
答案 1 :(得分:0)
AsyncTask
分为onPreExecute()
,onProgressUpdate()
和onPostExecute()
,所有这些都发生在主UI线程中,允许您对视图进行充气。只有doInBackground()
才是其他线程中实际发生的事情。如果您可以对此方法进行计算,只会使onProgressUpdate()
或onPostExecute()
膨胀,则可能有所帮助。
此外,如果您可以向我们提供您的代码,它可能有助于我们找到一种方法来提高CPU效率。
无论如何,如果UI线程的响应时间超过5秒,android将尝试强制关闭你的应用程序,并且就此而言并不多了(据我所知)。