Realm对象只能在创建它们的线程上访问_ Volley和AsyncTask

时间:2016-08-30 14:23:20

标签: android android-asynctask realm

我已经针对这个问题找到了类似的问题,但找不到答案

SO question1SO question2SO 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类中使用相同的行获取领域对象。我在这里犯的错是什么。

2 个答案:

答案 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访问它时,您将收到该错误。