0

私の Android アプリケーションは、データ保護とクラウドとの連携を実装しています。 アプリケーションは UI とスタンドアロン サービス (独自のプロセスで実行) で構成されます。 UI とサービス間の通信に IPC(Messages & Handlers) を使用しています。

次の状況があります-データを操作する前に、データのサイズとデータ項目の数を知る必要があります (連絡先、写真などを列挙し、進行状況の合計情報を収集する必要があります)。

問題について: サービス側で列挙が開始されると (スレッドプールで 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);
4

1 に答える 1

0

あなたは十分な情報を提供しなかったと言わざるを得ません (原因として疑われるコードの部分..) が、私の知識と経験から、知識に基づいた推測を行うことができます -

おそらく、実行に時間がかかる UI スレッド (メイン スレッド) でコードを実行しています。また、このコードは次のようにも推測できます: cotacts / gallery provider for all data.

ご存じない場合は、Serviceコールバック メソッドもメイン スレッド (UI スレッド..) から実行されます。ただし、別のスレッドから明示的に実行しない限りAsyncTask、コンテンツ プロバイダーにクエリを実行し、返されたデータのカーソルを処理することも重い操作になる可能性があります。メイン UI スレッドをブロックしないように、別のスレッドから実行する必要があります。

この高価なクエリを別のスレッドに実行するコードを削除した後、フリーズが発生する理由はありません。

于 2013-09-20T16:26:10.193 に答える