У меня есть код, который загружает JSON текущего объекта. Но этот же код должен вызываться IntentService всякий раз, когда будильник отключается (когда приложение не запускает какой-либо пользовательский интерфейс), а также AsyncTask во время работы приложения.Ошибка доступа с неправильной строки при использовании общего кода между IntentService и AsyncTask (Android)
Однако, я получил сообщение об ошибке Realm access from incorrect thread. Realm objects can only be accessed on the thread they were created.
Однако, я не понимаю, как и почему эта трассировка стека попала на другой поток.
Мне удалось избавиться от этой ошибки, скопировав весь общий код и вставив его непосредственно в метод DownloadDealService onHandleIntent
, но он очень неряшлив и я ищу лучшее решение, которое не требует дублирования кода.
Как я могу избавиться от этой ошибки без дублирующего кода? Благодарю.
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;
}
}
Стек след:
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)
У меня есть AsyncTask, что вызывает некоторые из этих методов Utils также:
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);
}
}
Вы можете посмотреть на мой код и скажите мне, где я проходил мимо ничего между потоками? Я не понимаю. Я честно думал, что я был в той же теме. Насколько я знаю, я только делил методы между потоками, а не пропускал любые объекты области между потоками. –
Трудно понять, что происходит, когда из примера кода.Но я предполагаю, что вы получите объект result в doInBackround AsyncTask (который выполняется в рабочем потоке), а затем передайте его в результате toPostExecute() (который выполняется в основном потоке). И затем попытаемся получить доступ к нему оттуда по методу restder(), который взорвет ваше приложение. –
Вы можете посмотреть в трассировке стека, которую я предоставил, чтобы увидеть путь выполнения. IntentService 'DownloadDealService' вызывает некоторые статические методы в моем классе' Util.java'. –