Error de acceso de realm de subproceso incorrecto al usar código compartido entre IntentService y AsyncTask (Android)
Tengo un cierto código que descargue un objeto "actual" JSON. Pero este mismo código debe ser llamado por un IntentService cada vez que una alarma se apaga (cuando la aplicación no está ejecutando cualquier interfaz de usuario), y también por un AsyncTask mientras la aplicación se está ejecutando.
Sin embargo, recibí un error diciendo 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 ni por qué este seguimiento de pila se ha puesto en un hilo diferente.
- Realm.io no puede conseguir ejemplos para trabajar
- Android Realm número de versión de migración basado en qué?
- Java.lang.NoClassDefFoundError: Resolución fallida de: Lio / realm / internal / SharedRealm $ Durabilidad
- ¿Métodos personalizados en la solución RealmObjects ...?
- Realm creado con Android en un proyecto no es válido en Otro
Yo era capaz de deshacerse del error copiando todo el código compartido y pegándolo directamente en el método onHandleIntent
de onHandleIntent
, pero es muy descuidado y estoy buscando una solución mejor que no requiere duplicar 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; } }
Rastro de la 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 un AsyncTask que llama algunos de esos métodos de Utils también:
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); } }
- Archivo default.realm no se muestra en el navegador de cromo
- Prueba de Android Realm con RxJava - "abierto desde un hilo sin un Looper" Excepción
- Builder (android.content.Context) 'no es público en' io.realm.RealmConfiguration.Builder '. No se puede acceder desde el paquete exterior
- Realm.io y consultas asincrónicas
- Acceso al dominio desde un subproceso incorrecto Excepción mientras se envió una copia usando copyFromRealm
- Android Realm - Actualización de RealmList dispara IllegalArgumentException
- ¿He usado Singleton con Realm Database correcto?
- No se puede agregar un nuevo objeto a RealmList debido a la referencia de objeto null
[UPDATED] basado en la información adicional
RealmDatabase.getInstance () devolvió la instancia de Realm creada en el subproceso principal. Y esta instancia se utilizó en el subproceso de IntentService. Que conducen al accidente.
Las instancias de Realm no se pueden utilizar en ningún otro subproceso excepto en el que se crearon.
No puede pasar objetos de Realm entre los subprocesos. Lo que puede hacer es pasar un identificador único del objeto (es decir, @PrimaryKey), y luego buscar 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:
- Uso de un dominio a través de los hilos https://realm.io/docs/java/latest/
- Ejemplo de hilo https://github.com/realm/realm-java/tree/master/examples/threadExample
El problema es que está llamando a métodos de diferentes hilos, tiene que usar el mismo hilo, crear su propio HandlerThread.
Si utiliza el Realm en IntentService, usará Realm nuevo. Por ejemplo
Realm.getInstance(RealmConfiguration config)
He utilizado el Reino en IntentService
@Override protected void onHandleIntent(Intent intent) { Realm realm = Realm.getDefaultInstance(); ... realm.close(); // important on background thread }
- Construir proyecto android con Jenkins: No se pudo inicializar análisis
- Dibujo personalizado en la lona del mapa de Mapbox