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:
- Realm.getInstance (context) no funciona más después de la migración
- Generar error con Realm
- Declaración de actualización en Realm
- ¿Cómo se comprueba si ya se ha cerrado una instancia de reino?
- ¿Cómo puedo crear una base de datos Realm con datos iniciales para mi aplicación android?
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:
- Cómo actualizar sólo valores NOT NULL al escribir datos en Realm
- Error del compilador: com.sun.tools.javac.code.Symbol $ CompletionFailure: archivo de clase para rx.Observable no encontrado
- Realm Android - ¿Cómo puedo convertir RealmResults a una matriz de objetos?
- Realm ORM: cómo tratar con Maps?
- Android Realm copyToRealmOrUpdate actualiza los campos existentes
- ¿Los modelos Realm realmente requieren getters y setters?
- Insertar imagen en la base de datos del reino en android
- Realm Auto Incremento campo ejemplo
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.
- Android Studio – Tecla de acceso rápido para navegar a la declaración xml es en lugar de navegar hacia el archivo R
- Cómo usar kapt en el alcance de androidTest