Пропущено более 130 кадров, слишком много работы над основным потоком.

Я понимаю, что сетевые вызовы и доступ к sqlite лучше всего выполнять через рабочие потоки. В моем случае мои сетевые вызовы выполняются через Okhttp, а sqlite выполняется через один рабочий поток.

Итак, вот моя проблема. У меня есть основное действие, которое содержит все акции, которые пользователь купил в списке. Каждый раз, когда создается это новое действие, метод onCreate будет просматривать акции в базе данных и обновлять их одну за другой, а затем обновлять список.

Это, конечно, слишком сильно нагружает основной поток. Но моя проблема в том, как я могу спроектировать это лучше? Прямо сейчас у меня есть что-то вроде этого в onCreate:

Thread t1 = new Thread(new Runnable{
    @Override
    public void run(){
        // access sqlite
        positionsArray = retrieveStocks();
    }    
});
t1.start();
t1.join(); //try catch omitted 

Thread t2 = new Thread(new Runnable{
    @Override
    public void run(){
        // use Okhttp to get data
        positionsArray = refreshStocks();
    }    
});
t1.start();
t2.join(); //try catch omitted

adapter = new PositionsAdapter(this, positionsArray);
listview.setAdapter(adapter); 

Это не устраняет проблему, потому что основной поток все еще должен ждать t1 и t2. Любые дизайнерские предложения относительно того, как я могу решить эту проблему?


person jason adams    schedule 19.05.2016    source источник
comment
Ваш метод создания должен загружать текст, пока вы ждете завершения потоков.   -  person RMalke    schedule 19.05.2016
comment
Как насчет использования загрузчика?( developer.android.com/reference/android/app/ LoaderManager.html ) Вы можете сначала отобразить загружаемый текст (или кэшированные данные), а затем обновить данные после завершения загрузки.   -  person chartsai    schedule 19.05.2016
comment
да, но я все еще пропускаю более 130 кадров, я все еще получаю предупреждение о том, что в основном потоке сделано слишком много работы.   -  person jason adams    schedule 19.05.2016
comment
@Chatea, это звучит как хорошая идея, тоже не уверен, но поможет ли здесь добавление сервисов?   -  person jason adams    schedule 19.05.2016
comment
Служба используется для выполнения каких-либо действий, когда ваше приложение не находится на переднем плане. Если вам нужно сделать что-то только в потоке, отличном от пользовательского интерфейса, попробуйте AsyncTask, AsyncLoader или IntentService. Я думаю, вы должны определить, когда в первую очередь загружать сетевые данные.   -  person chartsai    schedule 19.05.2016
comment
Почему вы звоните join() из потока пользовательского интерфейса? Вызов join() приостанавливает текущий поток до завершения другого потока. Это означает, что ваши потоки не имеют никакой пользы.   -  person adelphus    schedule 19.05.2016


Ответы (1)


Вы никогда не должны вызывать thread.join() в потоке пользовательского интерфейса, так как это приостановит приложение. Вы можете использовать асинхронную задачу для этого примера AsyncTask для Android

ProgressDialog progress;
private class DoNetworking extends AsyncTask<Void, Void, PosArray> {

    @Override
    protected PosArray doInBackground() {
        positionsArray = retrieveStocks();
        positionsArray = refreshStocks();
        PosArray positionsArray;
    }

    @Override
    protected void onPostExecute(PosArray positionsArray) {
        adapter = new PositionsAdapter(this, positionsArray);
        listview.setAdapter(adapter); 
        progress.dismiss();
    }
}
progress = ProgressDialog.show(this, "dialog title","dialog message", true);
new DoNetworking().execute()
person Tomer Shemesh    schedule 19.05.2016
comment
поэтому, если я использую асинхронную задачу для установки адаптера, не придется ли основному потоку ждать возврата результатов? Разве основной поток не будет ждать установки списка, прежде чем он сможет отобразить его на экране? - person jason adams; 20.05.2016
comment
да, главный экран не будет обновляться, пока данные не вернутся, но экран не будет зависать, как это было у вас. Ваша задача — загрузить индикатор выполнения или диалоговое окно, пока пользователь ждет. Ив добавил пример для вас - person Tomer Shemesh; 20.05.2016
comment
Ах, хорошо, я понимаю, так что позвольте мне понять это прямо, использование AsyncTask позволит активности рисовать вещи без блокировки, и она может ждать AsyncTask столько времени, сколько потребуется? Также будет ли разумным вызывать Okhttp, чтобы совершать сетевые вызовы в AsyncTask? - person jason adams; 20.05.2016
comment
Да, собственно, в этом вся суть асинхронной задачи. для совершения сетевых вызовов и работы без блокировки потоков - person Tomer Shemesh; 20.05.2016