Erro de acesso ao território a partir de encadeamento incorreto ao usar código compartilhado entre IntentService e AsyncTask (Android)
Eu tenho algum código que baixa o JSON de um objeto "Atual". Mas esse mesmo código precisa ser chamado por um IntentService sempre que um alarme disparar (quando o aplicativo não está executando nenhuma interface do usuário) e também por uma AsyncTask enquanto o aplicativo está em execução.
No entanto, recebi um erro dizendoRealm access from incorrect thread. Realm objects can only be accessed on the thread they were created.
No entanto, não entendo como ou por que esse rastreamento de pilha entrou em um thread diferente.
Consegui me livrar do erro copiando todo o código compartilhado e colando-o diretamente no arquivo DownloadDealServiceonHandleIntent
, mas é muito desleixado e estou procurando uma solução melhor que não exija duplicação de código.
Como posso me livrar desse erro sem duplicar o código? Obrigado.
public class DownloadDealService extends IntentService
{
...
@Override
protected void onHandleIntent(Intent intent)
{
Current todaysCurrent = Utils.downloadTodaysCurrent(); //<--- included for background info
String dateString = Utils.getMehHeadquartersDate(); //(omitted)
Utils.onDownloadCurrentCompleteWithAlarm(todaysCurrent, dateString); //<------ calling this...
}
}
public class Utils
{
// ...other methods ommitted...
//This method is not in the stack trace, but I included it for background information.
public static Current downloadTodaysCurrent()
{
//Set up Gson object... (omitted)
//Set up RestAdapter object... (omitted)
//Set up MehService class... (omitted)
//Download "Current" object from the internet.
Current current = mehService.current(MehService.API_KEY);
return current;
}
//Included for background info- this method is not in the stack trace.
public static void onDownloadCurrentComplete(Current result, String dateString)
{
if(result.getVideo() == null)
{
Log.e("HomePage", "Current was not added on TaskComplete");
return;
}
remainder(result, dateString);
}
public static void onDownloadCurrentCompleteWithAlarm(Current result, String dateString)
{
//Set alarm if download failed and exit this function... (omitted)
remainder(result, dateString);//<------ calling this...
Utils.sendMehNewDealNotification(App.getContext());
}
public static void remainder(Current result, String dateString)
{
Realm realm = RealmDatabase.getInstance();
//Add "Current" to Realm
Current current = Utils.addCurrentToRealm(result, realm); //<------ calling this...
}
public static Current addCurrentToRealm(Current current, Realm realm)
{
realm.beginTransaction(); //<---- Error is here
Current result = realm.copyToRealmOrUpdate(current);
realm.commitTransaction();
return result;
}
}
Rastreio de pilha:
E/AndroidRuntime: FATAL EXCEPTION: IntentService[DownloadDealService]
Process: com.example.lexi.meh, PID: 13738
java.lang.IllegalStateException: Realm access from incorrect thread. Realm objects can only be accessed on the thread they were created.
at io.realm.Realm.checkIfValid(Realm.java:191)
at io.realm.Realm.beginTransaction(Realm.java:1449)
at com.example.lexi.meh.Utils.Utils.addCurrentToRealm(Utils.java:324)
at com.example.lexi.meh.Utils.Utils.remainder(Utils.java:644)
at com.example.lexi.meh.Utils.Utils.onDownloadCurrentCompleteWithAlarm(Utils.java:635)
at com.example.lexi.meh.Home.DownloadDealService.onHandleIntent(DownloadDealService.java:42)
at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.os.HandlerThread.run(HandlerThread.java:61)
Eu tenho um AsyncTask que chama alguns desses métodos Utils também:
public class DownloadAsyncTask extends AsyncTask<Void, Integer, Current>
{
// ... (more methods ommitted)...
protected Current doInBackground(Void... voids)
{
return Utils.downloadTodaysCurrent(); //<---- shared Utils method
}
}
//Async class's callback in main activity:
public class HomePage extends AppCompatActivity implements DownloadAsyncTaskCallback, DownloadAsyncTaskGistCallback<Current, String>
{
// ... (more methods ommitted)...
public void onTaskComplete(Current result, String dateString)
{
Utils.onDownloadCurrentComplete(result, dateString);
}
}