Realm "Zugriff von falschem Thread" -Fehler bei Verwendung von gemeinsam genutztem Code zwischen IntentService und AsyncTask (Android)

Ich habe Code, der die JSON eines "aktuellen" Objekts herunterlädt. Derselbe Code muss jedoch von einem IntentService aufgerufen werden, wenn ein Alarm ausgelöst wird (wenn die App keine Benutzeroberfläche ausführt), und auch von einer AsyncTask, während die App ausgeführt wird.

Ich habe jedoch eine Fehlermeldung erhalten:Realm access from incorrect thread. Realm objects can only be accessed on the thread they were created. Allerdings verstehe ich nicht, wie oder warum dieser Stack-Trace auf einen anderen Thread gelangt ist.

Ich konnte den Fehler beheben, indem ich den gesamten freigegebenen Code kopierte und ihn direkt in DownloadDealService's @ einfügtonHandleIntent Methode, aber es ist sehr schlampig und ich bin auf der Suche nach einer besseren Lösung, bei der kein Code dupliziert werden muss.

Wie kann ich diesen Fehler beseitigen, ohne Code zu duplizieren? Vielen Dank

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;
    }
}

Stack trace:

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)

Ich habe eine AsyncTask, die einige dieser Utils-Methoden auch aufruft:

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);
    }
}

Antworten auf die Frage(6)

Ihre Antwort auf die Frage