我的安卓应用程序实现了数据保护和云工作。应用程序由 UI 和独立服务(在自己的进程中运行)组成。我正在使用IPC(消息和处理程序)在UI和服务之间进行通信。
我有下一种情况 - 在处理数据之前,我需要了解数据大小和数据项计数(我必须枚举联系人、照片等并收集进度的总信息)。
关于问题:当枚举在服务端开始时(它在线程池中使用 4 个运行线程),我的 UI 会冻结几秒钟(取决于总数据大小)。
有没有人知道任何方法可以使UI工作良好 - 而不会在这一刻冻结?
更新:这是我在服务中使用的 ThreadPoolExecutor 包装器来执行估计任务(创建类似于新的 ThreadPoolWorker(4,4,10)):
public class ThreadPoolWorker {
private Object threadPoolLock = new Object();
private ThreadPoolExecutor threadPool = null;
private ArrayBlockingQueue<Runnable> queue = null;
private List<Future<?>> futures = null;
public ThreadPoolWorker(int poolSize, int maxPoolSize, int keepAliveTime){
queue = new ArrayBlockingQueue<Runnable>(5);
threadPool = new ThreadPoolExecutor(poolSize, maxPoolSize, keepAliveTime, TimeUnit.SECONDS, queue);
threadPool.prestartAllCoreThreads();
}
public void runTask(Runnable task){
try{
synchronized (threadPoolLock) {
if(futures == null){
futures = new ArrayList<Future<?>>();
}
futures.add(threadPool.submit(task));
}
}catch(Exception e){
log.error("runTask failed. " + e.getMessage() + " Stack: " + OperationsHelper.StringOperations.getStackToString(e.getStackTrace()));
}
}
public void shutDown()
{
synchronized (threadPoolLock) {
threadPool.shutdown();
}
}
public void joinAll() throws Exception{
synchronized (threadPoolLock) {
try {
if(futures == null || (futures != null && futures.size() <= 0)){
return;
}
for(Future<?> f : futures){
f.get();
}
} catch (ExecutionException e){
log.error("ExecutionException Error: " + e.getMessage() + " Stack: " + OperationsHelper.StringOperations.getStackToString(e.getStackTrace()));
throw e;
} catch (InterruptedException e) {
log.error("InterruptedException Error: " + e.getMessage() + " Stack: " + OperationsHelper.StringOperations.getStackToString(e.getStackTrace()));
throw e;
}
}
}
}
以下是启动我使用的枚举任务的方法:
estimateExecutor.runTask(contactsEstimate);
我必须说你没有提供足够的信息(你怀疑是原因的代码部分......但根据我的知识和经验,我可以做出有根据的猜测——
您可能正在 UI 线程(主线程)上执行代码,它执行需要一段时间。 我也可以猜测这段代码是:查询cotacts/画廊提供者的所有数据。
如果您不知道 - Service
回调方法也从主线程(UI 线程..) 除非明确地从AsyncTask
/另一个线程运行它们,并且查询内容提供程序并处理它返回的游标以获取数据也可能是繁重的操作,需要从另一个线程执行,以免阻塞主 UI 线程。
删除对另一个线程执行此昂贵查询的代码后 - 没有理由遇到任何冻结。