'Android, how to initiate realm in AsyncTask?

I have an asyncTask in my application as below. I have to fetch data from realm(which is successfully stored in another activity) into this AsyncTask. Below is my AsyncTask code:

public class MakeAsyncRequest extends AsyncTask<Object, String, MakeAsyncRequest.ResponseDataType>{

public Context asyncContext;
    private MakeAsyncRequest(Context context){
        asyncContext = context;
    }

private static final OkHttpClient client = new OkHttpClient();
private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");

private MakeRequest.ResponseHandler handler;
private String method;
private User user;
private Realm realm;


class ResponseDataType
{
    InputStream inputStream;
    String string;
    String cookie;
}
MakeAsyncRequest(MakeRequest.ResponseHandler responseHandler, String type)
{
    method = type;
    handler = responseHandler;
}


@Override

protected ResponseDataType doInBackground(Object... params) {
    try {
        Requests requests = new Requests((Context) params[0]);
        String url = params[1].toString();
        String bodyJson = null;
        if(method.equals("PUT") || method.equals("POST")) {
            bodyJson = params[2].toString();
        }
        final Request.Builder builder;
        Response response;
        RequestBody body;
        switch (method) {

            case "GET": builder = new Request.Builder().url(url);
                break;

            case "DOWNLOAD": builder = new Request.Builder().url(url);
                break;

            case "POST": body = RequestBody.create(JSON, bodyJson);
                builder = new Request.Builder()
                        .url(url)
                        .post(body)
                        .addHeader("Cookie", "key=value");
                break;

            case "PUT":  body = RequestBody.create(JSON, bodyJson);
                builder = new Request.Builder()
                        .url(url)
                        .put(body);
                break;

            default: builder = new Request.Builder().url(url);
        }
        builder.addHeader("Accept", "application/json");
        realm = RealmController.initialize(this).getRealm();
        final RealmResults<User> users = realm.where(User.class).findAllAsync();
        user = users.first();
        if(user.getCookie() !== null && !user.getCookie().isEmpty()){
            builder.addHeader("cookie", "user.getCookie()");
        }
        response = client.newCall(builder.build()).execute();
        ResponseDataType responseDataType = new ResponseDataType();
        if(method.equals("DOWNLOAD")) { responseDataType.inputStream = response.body().byteStream(); }
        else {
            responseDataType.string = response.body().string();
            responseDataType.cookie = response.headers().get("set-cookie");
            CookieManager cManager = new CookieManager(null, CookiePolicy.ACCEPT_ALL);
            cManager.getCookieStore().getCookies();
        }
        return  responseDataType;

    } catch (IOException e) {
        return null;
    }
}

@Override
protected void onPostExecute(ResponseDataType response) {
    try {
        if (method.equals("DOWNLOAD")) {
            handler.onFinishCallback(response.inputStream);
        }else {
            handler.onFinishCallback(response.string, response.cookie);
            CookieManager cManager = new CookieManager(null, CookiePolicy.ACCEPT_ALL);
            cManager.getCookieStore().getCookies();
        }
    }catch (Exception e){
        Log.d("hExceptionError", e.toString());
        handler.onFinishCallback("{\n" +
                "  \"error\": \"error\"\n" +
                "}","");
    }
}

I am received the access error - "Realm access from incorrect thread. Realm objects can only be accessed on the thread they were created." whenever the control tries to execute the Realm results or to get the first object from Realm.

Below is my RealmController which i created to control the realm instance:

public class RealmController {`public static RealmController initialize(Activity activity) {

    if (instance == null) {
        instance = new RealmController(activity.getApplication());
    }
    return instance;
}
public static RealmController initialize(MakeAsyncRequest activity) {

    if (instance == null) {
        instance = new RealmController(activity.);
    }
    return instance;
}
}`

I have my user model(Realm object) with setters and getters.



Solution 1:[1]

The point is - you cannot create and access Realm on different threads, i.e. create Realm instance in Activity and use it in .doInBackground() method. Create and release Realm immediately before and after transaction. There may be another issue - don't register quer observer on background thread in AsyncTask - it doesn't have Looper initialized - use main thread or HandlerThread. Release realm after it is no longer needed (you didn't in your code), because Realm has limited number of instances.

Solution 2:[2]

put Realm.getDefaultInstance() inside doInBackground

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Alex Shutov
Solution 2 Basheer Adel