我已经针对这个问题找到了类似的问题,但找不到答案
SO question1,SO question2和SO question3
我的应用程序流程处于按钮单击状态,使用Volley
按如下方式请求网络。仅包含相关代码。在以下行中进入ActivityCustomer
时出错
Object obj = realmObj.where(ExplorerFolderData.class)
.equalTo(Constants.DBPARENTID,"0")
.or()
.equalTo(Constants.DBPARENTID,"-1")
.findAllAsync();
错误:
引起:java.lang.IllegalStateException:Realm访问来自 错误的线程。只能在线程上访问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) 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)活动类 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类中使用相同的行获取领域对象。我在这里犯的错是什么。
答案 0 :(得分:3)
使用单例设置的方式只有1个Realm实例。
如果在线程A中调用realmProcessor.getRealm();
,然后在线程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实例以确保它被关闭。
查看更多in the docs
答案 1 :(得分:2)
问题是你的Realm
对象在第一次调用RealmProcessor.with
时只创建一次(因为它是单例)。让我们说JsonProcessor::getThingList
发生在线程#1和{{ 1}}发生在另一个线程#2上。
因此,如果ExplorerDBOperation::doInBackground()
调用将在JsonProcessor::getThingList
之前,则Realm对象将绑定到线程#1,当您尝试从线程#2访问它时,您将收到该错误。