在我的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