Acceso al dominio desde un subproceso incorrecto

Tengo una aplicación con una LoginActivity , que cuando el usuario inicia sesión correctamente, me registro para recibir mensajes. Y la LoginActivity salta a MainActivity . Se supone que los mensajes que llegan se almacenan en la base de datos (Realm), para recuperarse de una instancia de Realm en Main.

Pero cuando llega el mensaje El reino del accidente lanzando este errror:

 Exception in packet listener java.lang.IllegalStateException: Realm access from incorrect thread. Realm objects can only be accessed on the thread they were created. at io.realm.BaseRealm.checkIfValid(BaseRealm.java:383) at io.realm.Realm.executeTransactionAsync(Realm.java:1324) at io.realm.Realm.executeTransactionAsync(Realm.java:1276) at es.in2.in2tant.LoginActivity.newMessageReceived(LoginActivity.java:124) at es.in2.in2tant.Connection.Connection$4$1.processMessage(Connection.java:227) at org.jivesoftware.smack.chat.Chat.deliver(Chat.java:180) at org.jivesoftware.smack.chat.ChatManager.deliverMessage(ChatManager.java:351) at org.jivesoftware.smack.chat.ChatManager.access$300(ChatManager.java:53) at org.jivesoftware.smack.chat.ChatManager$2.processPacket(ChatManager.java:162) at org.jivesoftware.smack.AbstractXMPPConnection$4.run(AbstractXMPPConnection.java:1126) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) at java.lang.Thread.run(Thread.java:818) 

Estoy un poco perdido en cómo funciona Realm, y no sé cómo hacer que el reino accesible a través de la aplicación sin un accidente y mantener el almacenamiento de estos mensajes recibidos de LoginActivity . ¿Alguna ayuda, o enfoques para lograr esto?

LoginActivity.java :

 public class LoginActivity extends AppCompatActivity implements ConnectionConnectResponse { ..... protected void onCreate(Bundle savedInstanceState) { //Realm Init config: Realm.init(this); RealmConfiguration realmConfiguration = new RealmConfiguration.Builder().build(); Realm.deleteRealm(realmConfiguration); // Clean slate Realm.setDefaultConfiguration(realmConfiguration); // Make this Realm the default @Override public void newMessageReceived(final ChatMessage message) { Logger.d("NEWMESSAGERECEIVED :" + message); realm.executeTransactionAsync(new Realm.Transaction() { @Override public void execute(Realm realm) { Message receivedMessage = realm.createObject(Message.class, message.id); receivedMessage.setBodyMessage(message.message); receivedMessage.setFrom(message.from); receivedMessage.setTo(message.to); receivedMessage.setDelivered(false); receivedMessage.setMine(false); receivedMessage.setDate(Calendar.getInstance().getTime()); } }); //Logger.d("NEWMESSRE: LAST MESSAGE:" + realm.where(Message.class).equalTo("chatID", message.id)); } @Override protected void onStart() { super.onStart(); realm = Realm.getDefaultInstance(); } @Override protected void onStop() { super.onStop(); realm.close(); } 

Imagen de lo que se necesita:

Introduzca aquí la descripción de la imagen

Acceso de dominio desde un subproceso incorrecto. Sólo se puede acceder a los objetos de dominio en el subproceso que se creó.

Este mensaje de error es bastante auto-explicativo.

Como veo que está inicializando el realm llamando a Realm.getDefaultInstance() en el subproceso de la interfaz de usuario.

El error es de newMessageReceived() , así que supongo que el método se llama desde un subproceso de fondo.

Obtenga una instancia de Realm en el subproceso de fondo y utilícela en lugar de una instancia global:

 @Override public void run () { Realm backgroundRealm = Realm.getDefaultInstance(); backgroundRealm.executeTransactionAsync(new Realm.Transaction() { @Override public void execute(Realm realm) { Message receivedMessage = realm.createObject(Message.class, message.id); receivedMessage.setBodyMessage(message.message); receivedMessage.setFrom(message.from); receivedMessage.setTo(message.to); receivedMessage.setDelivered(false); receivedMessage.setMine(false); receivedMessage.setDate(Calendar.getInstance().getTime()); } }); } 

O bien , si por alguna razón desea adherirse a una instancia de Realm global, asegúrese de ejecutar el código en el subproceso de UI llamando a runOnUiThread() (o publicando un Runnable en la cola de mensajes del subproceso principal):

 @Override public void newMessageReceived(final ChatMessage message) { runOnUiThread(new Runnable() { @Override public void run() { realm.executeTransactionAsync(new Realm.Transaction() { @Override public void execute(Realm realm) { Message receivedMessage = realm.createObject(Message.class, message.id); receivedMessage.setBodyMessage(message.message); receivedMessage.setFrom(message.from); receivedMessage.setTo(message.to); receivedMessage.setDelivered(false); receivedMessage.setMine(false); receivedMessage.setDate(Calendar.getInstance().getTime()); } }); } }); } 

Asigne la instancia antes de la transacción y libérela justo después de que la transacción esté completa, por lo que no tendrá conexión de línea y, al hacerlo, realizará los ahorros del programador de subprocesos. Yo uso "Data Access Object" interfaz para manipulaciones con datos y que la interfaz se implementa utilizando Realm. No utilice 'asincronía de transacción', utilice todas las llamadas de forma sincrónica, sino que realice llamadas en 'objeto de acceso a datos' desde el subproceso de fondo. Buena solución para eso – rxJava biblioteca. Basta con obtener y liberar instancia de Realm todo el tiempo – la biblioteca hace que sea barato.

Todavía no uso Realm. Pero lo que entendí del mensaje de error es que ConnectionConnectResponse puede estar vivo cuando mueren Loginactivity. Por lo tanto, debe pasar instancia de Realm como un parámetro dentro

newMessageReceived(Realm realm, final ChatMessage message)

Y poner todo el código init de Realm en la clase donde se dispara este método.

  • Realm Exception 'value' no es un objeto gestionado válido
  • Adición de objetos independientes a una RealmList
  • ¿Cuál es la mejor manera de usar List <String> en Realm Android?
  • Cómo hacer una copia de seguridad de Realm DB en Android antes de eliminar el archivo Realm. ¿Hay alguna manera de restaurar el archivo de copia de seguridad?
  • Realm Query es posible usar IN?
  • Cómo utilizar Realm asObservable con el operador concat () de RxJava?
  • "Necesita migración de realm", excepción en android mientras recupera valores de dm del reino
  • Cómo cerrar el reino abierto por Realm.getDefaultInstance?
  • Requisito de dominio con dos condiciones al mismo tiempo
  • Consulta de dominio con Lista
  • Resultados de Limit Realm
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.