vivo studio siempre servicio primer plano mantener example entre enhanced ejemplo diferencia crear asynctask android multithreading android-asynctask realm android-intentservice

studio - Error de "acceso desde el subproceso incorrecto al usar código compartido entre IntentService y AsyncTask(Android)



intentservice example (3)

Tengo un código que descarga el JSON de un objeto "Actual". Pero este mismo código debe ser llamado por un IntentService cada vez que suena una alarma (cuando la aplicación no está ejecutando ninguna interfaz de usuario), y también por un AsyncTask mientras la aplicación se está ejecutando.

Sin embargo, recibí un error diciendo que el Realm access from incorrect thread. Realm objects can only be accessed on the thread they were created. Realm access from incorrect thread. Realm objects can only be accessed on the thread they were created. Sin embargo, no entiendo cómo o por qué esta traza de pila se puso en un hilo diferente.

Pude deshacerme del error al copiar todo el código compartido y onHandleIntent directamente en el método onHandleIntent de onHandleIntent , pero es muy descuidado y estoy buscando una mejor solución que no requiera duplicar el código.

¿Cómo puedo deshacerme de este error, sin duplicar el código? Gracias.

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

Rastreo de pila:

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)

Tengo una AsyncTask que también llama a algunos de esos métodos de 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); } }


El problema es que estás llamando a métodos de diferentes hilos, tienes que usar el mismo hilo, crea tu propio HandlerThread.


Si usa el Reino en IntentService, usará el nuevo Reino .por ejemplo

Realm.getInstance(RealmConfiguration config)

Usé el Reino en IntentService

@Override protected void onHandleIntent(Intent intent) { Realm realm = Realm.getDefaultInstance(); ... realm.close(); // important on background thread }


[ACTUALIZADO] basado en la información adicional

RealmDatabase.getInstance () estaba devolviendo la instancia de Realm creada en el hilo principal. Y esta instancia fue utilizada en el hilo de IntentService. Lo que llevó al accidente.

Las instancias de reino no se pueden usar en ningún otro hilo, excepto en el que se crearon.

No puedes pasar objetos de reino entre los hilos. Lo que puede hacer es pasar un identificador único del objeto (es decir, @PrimaryKey), y luego obtener el objeto por su id en otro hilo. Así: realm.where (YourRealmModel.class) .equalTo ("primaryKeyVariable", id) .findFirst ().

Para más detalles, consulte la documentación oficial de Realm y el ejemplo: