我已经解决了这个问题的类似问题,但找不到答案
所以问题1 , 问题2和问题3
我的应用程序流程是按钮点击,使用Volley按如下方式请求网络。 只包括相关的代码。 在以下行中访问ActivityCustomer时出错
Object obj = realmObj.where(ExplorerFolderData.class) .equalTo(Constants.DBPARENTID,"0") .or() .equalTo(Constants.DBPARENTID,"-1") .findAllAsync();错误:
由:java.lang.IllegalStateException引起:Realm从不正确的线程访问。 领域对象只能在创建它们的线程上访问。
1) MyApplication
public class MyApplication extends Application { private static Context appContext; @Override public void onCreate() { super.onCreate(); RealmConfiguration realmConfiguration = new RealmConfiguration.Builder(this) .name(Realm.DEFAULT_REALM_NAME) .schemaVersion(0) .deleteRealmIfMigrationNeeded() .build(); Realm.setDefaultConfiguration(realmConfiguration); appContext = getApplicationContext(); } public static Context getAppContext(){ return appContext; } }2)接口OnAsyncTaskComplition
//This interface will get back the status to Activity/Fragment public interface OnAsyncTaskComplition { public void networkResponse(ResultObject responseObject); }3) 网络处理器
public class NetworkProcessor{ private OnAsyncTaskComplition mCaller; public NetworkProcessor(Activity activity){ //setting caller Activity/Fragment to get back data mCaller=(OnAsyncTaskComplition)activity; processNetworkData(); } //Method for Volley Network Procesing public void processNetworkData(){ JsonObjectRequest jsonObjReq = new JsonObjectRequest(methodReq,urlBuffer.toString(),null, new Response.Listener<JSONObject>(){ @Override public void onResponse(JSONObject response) { JsonProcessor jsonProcessor=new JsonProcessor(); mCaller.networkResponse(jsonProcessor.getThingList(response)); } }, new Response.ErrorListener(){ @Override public void onErrorResponse(VolleyError error) { //Handle error also back to caller } }); } }4) JsonProcessor
public class JsonProcessor { public status void getThingList(JSONObject response){ boolean status=false; try{ RealmProcessor realmProcessor=RealmProcessor.with(MyApplication.getAppContext()); Realm realmObj = realmProcessor.getRealm(); //Code for setting values to RealmObject class ExplorerFolderData realmObj.beginTransaction(); realmObj.copyToRealm(ExplorerFolderData RealmObject which has values populated); realmObj.commitTransaction(); status=true; }catch(Exception e){ } } }5) RealmProcessor
public class RealmProcessor { private static RealmProcessor instance; private Realm realm; private RealmProcessor(Context context) { realm = Realm.getDefaultInstance(); } public static RealmProcessor with(Context context) { if (instance == null) { instance = new RealmProcessor(context); } return instance; } public Realm getRealm() { return realm; } }6)Activity类ActivityCustomer
public class ActivityCustomer extends AppBaseActivity implements OnAsyncTaskComplition { //Method called on Button click private void callNetwork(){ new NetworkProcessor(this); } @Override public void networkResponse(ResultObject responseObject) { new ExplorerDBOperation().execute(); } class ExplorerDBOperation extends AsyncTask<Void,Boolean,Boolean> { ProgressDialog dialog; @Override protected Boolean doInBackground(Void... params) { RealmProcessor realmProcessor=RealmProcessor.with(MyApplication.getAppContext()); Realm realmObj = realmProcessor.getRealm(); //ERROR OVER HERE Object obj = realmObj.where(ExplorerFolderData.class) .equalTo(Constants.DBPARENTID,"0") .or() .equalTo(Constants.DBPARENTID,"-1") .findAllAsync(); return true; } }我在Activity和JsonProcessor类中使用相同的行获取领域对象。 我在这里犯了什么错误。
I already gone through these similar questions for the issue, but could not find the answer
SO question1 , SO question2 and SO question3
My application flow is on button click, network is requested as follows using Volley. Included only relevant code . Error getting in ActivityCustomer in the following line
Object obj = realmObj.where(ExplorerFolderData.class) .equalTo(Constants.DBPARENTID,"0") .or() .equalTo(Constants.DBPARENTID,"-1") .findAllAsync();Error:
Caused by: java.lang.IllegalStateException: Realm access from incorrect thread. Realm objects can only be accessed on the thread they were created.
1) MyApplication
public class MyApplication extends Application { private static Context appContext; @Override public void onCreate() { super.onCreate(); RealmConfiguration realmConfiguration = new RealmConfiguration.Builder(this) .name(Realm.DEFAULT_REALM_NAME) .schemaVersion(0) .deleteRealmIfMigrationNeeded() .build(); Realm.setDefaultConfiguration(realmConfiguration); appContext = getApplicationContext(); } public static Context getAppContext(){ return appContext; } }2) Interface OnAsyncTaskComplition
//This interface will get back the status to Activity/Fragment public interface OnAsyncTaskComplition { public void networkResponse(ResultObject responseObject); }3) NetworkProcessor
public class NetworkProcessor{ private OnAsyncTaskComplition mCaller; public NetworkProcessor(Activity activity){ //setting caller Activity/Fragment to get back data mCaller=(OnAsyncTaskComplition)activity; processNetworkData(); } //Method for Volley Network Procesing public void processNetworkData(){ JsonObjectRequest jsonObjReq = new JsonObjectRequest(methodReq,urlBuffer.toString(),null, new Response.Listener<JSONObject>(){ @Override public void onResponse(JSONObject response) { JsonProcessor jsonProcessor=new JsonProcessor(); mCaller.networkResponse(jsonProcessor.getThingList(response)); } }, new Response.ErrorListener(){ @Override public void onErrorResponse(VolleyError error) { //Handle error also back to caller } }); } }4) JsonProcessor
public class JsonProcessor { public status void getThingList(JSONObject response){ boolean status=false; try{ RealmProcessor realmProcessor=RealmProcessor.with(MyApplication.getAppContext()); Realm realmObj = realmProcessor.getRealm(); //Code for setting values to RealmObject class ExplorerFolderData realmObj.beginTransaction(); realmObj.copyToRealm(ExplorerFolderData RealmObject which has values populated); realmObj.commitTransaction(); status=true; }catch(Exception e){ } } }5) RealmProcessor
public class RealmProcessor { private static RealmProcessor instance; private Realm realm; private RealmProcessor(Context context) { realm = Realm.getDefaultInstance(); } public static RealmProcessor with(Context context) { if (instance == null) { instance = new RealmProcessor(context); } return instance; } public Realm getRealm() { return realm; } }6) Activity class ActivityCustomer
public class ActivityCustomer extends AppBaseActivity implements OnAsyncTaskComplition { //Method called on Button click private void callNetwork(){ new NetworkProcessor(this); } @Override public void networkResponse(ResultObject responseObject) { new ExplorerDBOperation().execute(); } class ExplorerDBOperation extends AsyncTask<Void,Boolean,Boolean> { ProgressDialog dialog; @Override protected Boolean doInBackground(Void... params) { RealmProcessor realmProcessor=RealmProcessor.with(MyApplication.getAppContext()); Realm realmObj = realmProcessor.getRealm(); //ERROR OVER HERE Object obj = realmObj.where(ExplorerFolderData.class) .equalTo(Constants.DBPARENTID,"0") .or() .equalTo(Constants.DBPARENTID,"-1") .findAllAsync(); return true; } }I am getting realm object using the same line in Activity as well as JsonProcessor class. What is the mistake I am making over here.
最满意答案
你使用单例设置的方式只有1个Realm实例。
如果你调用realmProcessor.getRealm(); 在线程A中,然后在线程B中再次调用它们,它们返回相同的实例。 Realm不允许在线程之间共享实例。 由于AsyncTask的doInBackground在单独的线程上运行,因此这不起作用。
更改为此将消除错误。 但是你有一些重新设计要做。
@Override protected Boolean doInBackground(Void... params) { Realm realmObj = Realm.getDefaultInstance(); try { Object obj = realmObj.where(ExplorerFolderData.class) .equalTo(Constants.DBPARENTID,"0") .or() .equalTo(Constants.DBPARENTID,"-1") .findAll(); } catch (Exception ex) { // handle error } finally { realmObj.close(); } return true; }请注意,您负责每个领域实例。 这意味着您必须手动确保您完成每个实例后关闭它。 AsyncTasks的一个常见做法是将doInBackground操作包装在try / catch / finally中,并关闭finally块中的realm实例以确保它被关闭。
在文档中查看更多内容
The way you are set up with the singleton you have only 1 Realm instance.
If you call realmProcessor.getRealm(); in thread A, and then call it again in thread B, they get back the same instance. Realm does not allow sharing instances between threads. Since the AsyncTask's doInBackground runs on a separate thread, this is not working.
Changing to this will rid you of the error. However you have some redesigning to do.
@Override protected Boolean doInBackground(Void... params) { Realm realmObj = Realm.getDefaultInstance(); try { Object obj = realmObj.where(ExplorerFolderData.class) .equalTo(Constants.DBPARENTID,"0") .or() .equalTo(Constants.DBPARENTID,"-1") .findAll(); } catch (Exception ex) { // handle error } finally { realmObj.close(); } return true; }Note that you are responsible for each and every realm instance. This means that you must manually ensure that you close every instance once you're done with it. A common practice for AsyncTasks is that you wrap your doInBackground operations in a try/catch/finally and close the realm instance in the finally block to ensure it gets closed.
See more in the docs
更多推荐
发布评论