Why Android Circle Progress Dialog Getting Freezes when Bunch of Data Syncing from Server to Local DB Using Retrofit
Asked Answered
F

4

10

1.Iam fetching Bulk of Data from Server and Inserting in the Local Database While Login in android.

2.For Syncing Purpose i have Used Retrofit Library, Syncing and Inserting Working Fine.

My Problem: While Syncing Bunch of Data from server Using Retrofit ,Circle Progress Dialog Getting Freeze.

Help me how to Fix this Issue.

EDIT:1

Called Retrofit method inside Async task ,Still Circle ProgressDialog Getting Freeze

//Calling the Async Task

Asynctask_Getdata task=new Asynctask_Getdata(TokenType_StringValue,Access_Token_StringValue, ID_StringValue);
   task.execute();

//AsyncTask MEthod

public class Asynctask_Getdata extends AsyncTask<String,Void,Void>
    {

        String TokenType_StringValueitem;
        String Access_Token_StringValueitem;
        String ID_StringValueitem;

        public Asynctask_Getdata(String tokenType_StringValueitem, String access_Token_StringValueitem, String ID_StringValueitem) {
            TokenType_StringValueitem = tokenType_StringValueitem;
            Access_Token_StringValueitem = access_Token_StringValueitem;
           ID_StringValueitem = ID_StringValueitem;
        }

        @Override
        protected void onPreExecute()
        {
            super.onPreExecute();

            if (!pDialog.isShowing())
            {
                pDialog.setIndeterminate(true);
                pDialog.setCanceledOnTouchOutside(false);
                pDialog.setMessage("Please Wait Getting Data...");
                pDialog.show();
            }
        }

        @Override
        protected void onPostExecute(Void aVoid)
        {

            super.onPostExecute(aVoid);
        }

        @Override
        protected Void doInBackground(String... params)
        {
            getLoginDataCall(TokenType_StringValueitem, Access_Token_StringValueitem, ID_StringValueitem );

            return null;
        }
    }


    private void getLoginDataCall(String TokenType_String, String Access_Token_StringValue, String RouteID_String) {

                String Tokenadd = TokenType_String + " Access_Token_StringValue;
                sisClient.getApi().getAllData(Tokenadd, RouteID_String,
                        new Callback<CommonResponse>() {
                            @Override
                            public void success(CommonResponse commonResponse, Response response) {

                                Timber.d("sendOtpAPICall%s", commonResponse.getStatusCode());

                                switch (commonResponse.getStatusCode()) {
                                    case 200:


                                        try {


                                            JSONArray jsonarray = null;
                                            try {
                                                jsonarray = new JSONArray(commonResponse.getRouteMaster());

                                                if (!commonResponse.getRouteMaster().equals("[]")) 
                                                 {
                                                    for (int i = 0; i < jsonarray.length(); i++) 
                                                      {
                                                        JSONObject jsonobject = jsonarray.getJSONObject(i);


                                                        RouteId_StringValue = jsonobject.getString("RouteId");



                                                        Asynxfor_Route_Master_insert(RouteId_StringValue);


                                                    }
                                                } else {
                                                    System.out.println("ROute Master Is NULL ::" + commonResponse.getStatusMessage() + "\n");
                                                }
                                            } catch (Exception e) {
                                                e.printStackTrace();
                                                ;
                                            }

                                      break;

                                    case 404:

                                        pDialog.dismiss();
                                        Toast.makeText(LoginPage.this, R.string.wrong_Username_or_password, Toast.LENGTH_LONG).show();

                                        break;
                                    case 500:
                                        pDialog.dismiss();
                                        Toast.makeText(LoginPage.this, R.string.something_wrong, Toast.LENGTH_LONG).show();
                                        break;

                                }
                            }

                            @Override
                            public void failure(RetrofitError error) {

                                try {
                                    if (error != null) {
                                        pDialog.dismiss();
                                        Timber.i("sendOtpAPICall error %s", error.getResponse().getStatus());
                                        String json = new String(((TypedByteArray) error.getResponse().getBody()).getBytes());
                                        Timber.i("failure  error %s", json.toString());

                                        JSONObject json1 = new JSONObject(json.toString());
                                        String json1string = json1.getString("StatusMessage");


                                        switch (error.getResponse().getStatus()) {
                                            case 404:
                                                Toast.makeText(getApplicationContext(), R.string.wrong_Username_or_password, Toast.LENGTH_LONG).show();
                                                break;
                                            case 500:
                                                Toast.makeText(LoginPage.this, R.string.something_wrong, Toast.LENGTH_LONG).show();
                                                break;
                                            default:
                                                Toast.makeText(LoginPage.this, json1string, Toast.LENGTH_LONG).show();
                                                break;
                                        }


                                    } else {
                                        Timber.i("failure  error %s", "Recieving error null rom server");
                                    }


                                } catch (Exception e) {
                                    e.printStackTrace();
                                    Toast.makeText(LoginPage.this, R.string.something_wrong, Toast.LENGTH_LONG).show();
                                }


                            }

                        });

            }
Featly answered 1/8, 2016 at 12:32 Comment(4)
Isn't this simply because the code is executed in the ui thread? Wrapping it in an async task should tell you right away if that's the problem. Retrofit always puts the parsing in a background thread (AFAIK) but you're somehow doing it as well in the main thread...Foulness
but i have Called this method inside async task but still Getting Freeze when Bulk data fetching from server to LocalDB:(Featly
how are you calling the execute method of your asyncTask? can you show the part of code?Clipper
@Clipper check my asyncTask execute MethodFeatly
B
3

There's no good reason to make a sync Retrofit call in this case, you should use an async call which is provided out of the box from Retrofit. It's very simple, and you can manage your ProgressBar states using the callbacks.

IMO you should not use AsyncTask at all. If you want to explore this check out this, this and this.

Example code conversion from Retrofit v1 sync call with AsyncTask, to Retrofit 2 async call, managed in api class and using Otto event bus for message passing:

public class ApiService {

    private static ApiService INSTANCE;

    // thwart instantiation by protecting
    protected ApiService() {
        // nothing
    }

    public static ApiService getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new ApiService();
        }
        return INSTANCE;
    }

    // -----------------------------------------------------------------------------------

    private static final String BASE_URL = "http://api.service.com/";

    private interface ApiServiceInterface {
        @GET("your/endpoint")
        Call<CommonResponse> postLogin(@Query("token_add") String tokenAdd, @Query("route_id") String RouteId);
    }

    private ApiServiceInterface apiServiceInterface = null;

    private ApiServiceInterface getInterface() {
        if (apiServiceInterface == null) {
            HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
            interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
            OkHttpClient client = new OkHttpClient.Builder()
                    .addInterceptor(interceptor)
                    .build();

            Retrofit retrofit = new Retrofit.Builder()
                    .client(client)
                    .baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();

            apiServiceInterface = retrofit.create(ApiServiceInterface.class);
        }
        return apiServiceInterface;
    }

    public void doGetData(Dialog pDialog, String TokenType_String, String Access_Token_StringValue, String RouteID_String) {
        if (!pDialog.isShowing())
        {
            pDialog.setIndeterminate(true);
            pDialog.setCanceledOnTouchOutside(false);
            pDialog.setMessage("Please Wait Getting Data...");
            pDialog.show();
        }
        String Tokenadd = TokenType_String + Access_Token_StringValue;
        getInterface().postLogin(Tokenadd, RouteID_String)
                .enqueue(new Callback<SocketCtrlResponse>() {
            @Override
            public void onResponse(Call<CommonResponse> call, Response<CommonResponse> response) {
                Timber.d("sendOtpAPICall%s", commonResponse.getStatusCode());
                switch (commonResponse.getStatusCode()) {
                    case 200:
                        JSONArray jsonarray = null;
                        try {
                            jsonarray = new JSONArray(commonResponse.getRouteMaster());

                            if (!commonResponse.getRouteMaster().equals("[]")) {
                                for (int i = 0; i < jsonarray.length(); i++) {
                                    JSONObject jsonobject = jsonarray.getJSONObject(i);
                                    RouteId_StringValue = jsonobject.getString("RouteId");
                                    //Asynxfor_Route_Master_insert(RouteId_StringValue);
                                    EventBus.getDefault().post(new GetDataResponseEvent(RouteId_StringValue));
                                }
                            } else {
                                System.out.println("ROute Master Is NULL ::" + commonResponse.getStatusMessage() + "\n");
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                      break;

                    case 404:
                        pDialog.dismiss();
                        Toast.makeText(LoginPage.this, R.string.wrong_Username_or_password, Toast.LENGTH_LONG).show();
                        EventBus.getDefault().post(new GetDataResponseEvent(""));
                        break;

                    case 500:
                        pDialog.dismiss();
                        Toast.makeText(LoginPage.this, R.string.something_wrong, Toast.LENGTH_LONG).show();
                        EventBus.getDefault().post(new GetDataResponseEvent(""));
                        break;
                }
            }

            @Override
            public void onFailure(Call<CommonResponse> call, Throwable t) {
                t.printStackTrace();
                pDialog.dismiss();
                Toast.makeText(LoginPage.this, R.string.something_wrong, Toast.LENGTH_LONG).show();
                EventBus.getDefault().post(new GetDataResponseEvent(""));
            }
        });
    }
}

You'll need an event class to wrap the data you expect to get back from the API, e.g.:

public class GetDataResponseEvent {
    private final String data;

    public GetDataResponseEvent(String data) {
        this.data = data;
    }

    public String getData() {
        return data;
    }
}

And as an example for calling the service from an Activity:

public class YourActivity extends Activity {
    Dialog pDialog;

    // ...

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // init pDialog, content view, etc.

        EventBus.getDefault().register(this);

        // ...
    }

    // ...

    public void getDataFromApi() {
        ApiService.getInstance().doGetData(pDialog, TokenType_StringValue,Access_Token_StringValue, ID_StringValue);
    }

    // ...

    public void onEvent(GetDataResponseEvent event) {
        String data = event.getData();
        Asynxfor_Route_Master_insert(data);
    }

    // ...
}

Note again that you'll have to upgrade to Retrofit 2 and use Otto. I've guessed this implementation so it mightn't work as is, but should be a good sketch to get the feel of it.

Bemused answered 9/8, 2016 at 10:57 Comment(2)
in retrofit 1.9 we can't add Progress bar?, My code Working fine ,only Progress bar getting Freeze.!!Featly
Using a ProgressBar is nothing to do with Retrofit as in the ProgressBar is UI (i.e. presentation) layer, while Retrofit is data access layer. If you insist on using AsyncTask, as others have said you can't access pDialog in the doInBackground method directly, you'd have to explicitly run it on the UI thread, e.g. by using runOnUiThread method as is explained here https://mcmap.net/q/1166686/-doing-ui-task-in-doinbackground-in-androidBemused
L
3

You can't use pDialog.dismiss();and Toast.makeText in doInBackground.

You must do it in a method, that has access to the UI thread like onProgressUpdate() and onPostExecute().

Lalonde answered 4/8, 2016 at 10:43 Comment(2)
here Dismiss is calling inside doinbackground is the Main reason for this issue?Featly
The reason is 'pDialog.dismiss();' and 'Toast.makeText'. You should pass the result of process in 'doinbackground' to 'onPostExecute()' .Check this link : https://mcmap.net/q/14811/-asynctask-android-exampleLalonde
B
3

There's no good reason to make a sync Retrofit call in this case, you should use an async call which is provided out of the box from Retrofit. It's very simple, and you can manage your ProgressBar states using the callbacks.

IMO you should not use AsyncTask at all. If you want to explore this check out this, this and this.

Example code conversion from Retrofit v1 sync call with AsyncTask, to Retrofit 2 async call, managed in api class and using Otto event bus for message passing:

public class ApiService {

    private static ApiService INSTANCE;

    // thwart instantiation by protecting
    protected ApiService() {
        // nothing
    }

    public static ApiService getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new ApiService();
        }
        return INSTANCE;
    }

    // -----------------------------------------------------------------------------------

    private static final String BASE_URL = "http://api.service.com/";

    private interface ApiServiceInterface {
        @GET("your/endpoint")
        Call<CommonResponse> postLogin(@Query("token_add") String tokenAdd, @Query("route_id") String RouteId);
    }

    private ApiServiceInterface apiServiceInterface = null;

    private ApiServiceInterface getInterface() {
        if (apiServiceInterface == null) {
            HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
            interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
            OkHttpClient client = new OkHttpClient.Builder()
                    .addInterceptor(interceptor)
                    .build();

            Retrofit retrofit = new Retrofit.Builder()
                    .client(client)
                    .baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();

            apiServiceInterface = retrofit.create(ApiServiceInterface.class);
        }
        return apiServiceInterface;
    }

    public void doGetData(Dialog pDialog, String TokenType_String, String Access_Token_StringValue, String RouteID_String) {
        if (!pDialog.isShowing())
        {
            pDialog.setIndeterminate(true);
            pDialog.setCanceledOnTouchOutside(false);
            pDialog.setMessage("Please Wait Getting Data...");
            pDialog.show();
        }
        String Tokenadd = TokenType_String + Access_Token_StringValue;
        getInterface().postLogin(Tokenadd, RouteID_String)
                .enqueue(new Callback<SocketCtrlResponse>() {
            @Override
            public void onResponse(Call<CommonResponse> call, Response<CommonResponse> response) {
                Timber.d("sendOtpAPICall%s", commonResponse.getStatusCode());
                switch (commonResponse.getStatusCode()) {
                    case 200:
                        JSONArray jsonarray = null;
                        try {
                            jsonarray = new JSONArray(commonResponse.getRouteMaster());

                            if (!commonResponse.getRouteMaster().equals("[]")) {
                                for (int i = 0; i < jsonarray.length(); i++) {
                                    JSONObject jsonobject = jsonarray.getJSONObject(i);
                                    RouteId_StringValue = jsonobject.getString("RouteId");
                                    //Asynxfor_Route_Master_insert(RouteId_StringValue);
                                    EventBus.getDefault().post(new GetDataResponseEvent(RouteId_StringValue));
                                }
                            } else {
                                System.out.println("ROute Master Is NULL ::" + commonResponse.getStatusMessage() + "\n");
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                      break;

                    case 404:
                        pDialog.dismiss();
                        Toast.makeText(LoginPage.this, R.string.wrong_Username_or_password, Toast.LENGTH_LONG).show();
                        EventBus.getDefault().post(new GetDataResponseEvent(""));
                        break;

                    case 500:
                        pDialog.dismiss();
                        Toast.makeText(LoginPage.this, R.string.something_wrong, Toast.LENGTH_LONG).show();
                        EventBus.getDefault().post(new GetDataResponseEvent(""));
                        break;
                }
            }

            @Override
            public void onFailure(Call<CommonResponse> call, Throwable t) {
                t.printStackTrace();
                pDialog.dismiss();
                Toast.makeText(LoginPage.this, R.string.something_wrong, Toast.LENGTH_LONG).show();
                EventBus.getDefault().post(new GetDataResponseEvent(""));
            }
        });
    }
}

You'll need an event class to wrap the data you expect to get back from the API, e.g.:

public class GetDataResponseEvent {
    private final String data;

    public GetDataResponseEvent(String data) {
        this.data = data;
    }

    public String getData() {
        return data;
    }
}

And as an example for calling the service from an Activity:

public class YourActivity extends Activity {
    Dialog pDialog;

    // ...

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // init pDialog, content view, etc.

        EventBus.getDefault().register(this);

        // ...
    }

    // ...

    public void getDataFromApi() {
        ApiService.getInstance().doGetData(pDialog, TokenType_StringValue,Access_Token_StringValue, ID_StringValue);
    }

    // ...

    public void onEvent(GetDataResponseEvent event) {
        String data = event.getData();
        Asynxfor_Route_Master_insert(data);
    }

    // ...
}

Note again that you'll have to upgrade to Retrofit 2 and use Otto. I've guessed this implementation so it mightn't work as is, but should be a good sketch to get the feel of it.

Bemused answered 9/8, 2016 at 10:57 Comment(2)
in retrofit 1.9 we can't add Progress bar?, My code Working fine ,only Progress bar getting Freeze.!!Featly
Using a ProgressBar is nothing to do with Retrofit as in the ProgressBar is UI (i.e. presentation) layer, while Retrofit is data access layer. If you insist on using AsyncTask, as others have said you can't access pDialog in the doInBackground method directly, you'd have to explicitly run it on the UI thread, e.g. by using runOnUiThread method as is explained here https://mcmap.net/q/1166686/-doing-ui-task-in-doinbackground-in-androidBemused
B
1

This is your RestInteface, where you define the calls to make

interface RestInterface {

    String BASE_URL = "https://you_have_to_specify.com/if_anything/";
    @GET("your_api")
    Call<ModelResponse> getRouteId(@Query String valueItem);
}

This is the implementation class, from where you call

public class RestService {

    private RestInterface restInterface;
    private OkHttpClient okHttpClient;
    public RestService() {

        OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();

        if (BuildConfig.DEBUG) {
            HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
            httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
            clientBuilder.addInterceptor(httpLoggingInterceptor);
        }
        okHttpClient = clientBuilder.build();

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(RestInterface.BASE_URL)
                .client(okHttpClient)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        restInterface = retrofit.create(RestInterface.class);

    }
    //this is the exposed method
    public void getRoute(String valueId, Callback<ModelResponse> callback){
            Call<ModelResponse> call = restInterface.getRouteId(valueId);
            call.enque(callback);

    }
}

This class should be in the format of your received response

public class ModelResponse{

    String RouteId;

    public String getRouteId(){
        return RouteId; 
    }
}

Now from your activity(or your preferred class), create an object of RestService, and call the method getRoute(), passing your query string and an anonymous callback object(retrofit 2 Callback interface) as parameters. You will get the result in the anonymous callback object as Response. // Added later Your implementation class

public class FromWhereYourApiIsCalled{
    RestService restService = new RestService();
    public void callRouteIdMethod(String value){
      progressDialog.show();// define progress dialog before
      restService.getRoute(value, new Callback<ModelResponse>() {
                @Override
                public void onResponse(Call<ModelResponse> call, Response<ModelResponse> response) {
                    progressDialog.dismiss();
                    Log.v("route Id", response.body().getRouteId());
                }

                @Override
                public void onFailure(Call<ModelResponse> call, Throwable t) {
                    progressDialog.dismiss();
                }
            });
    }
}
Bouillon answered 10/8, 2016 at 7:52 Comment(2)
where is my progress Bar?Featly
I have added an implementation class, at the bottom. check itBouillon
B
1

There are two possible causes of freezing problem.

First: your request operation is running on the UI thread of the application, which is not recommended.

Second: you are trying to test your app on some old device, which has old processor.

I would suggest you using Retrofit's own asynchronous requests, which is described here.The guy who told you that you should not call dialog.dismiss() on the main thread is right. It can freeze your app as well. Here is a good example how to avoid it using method runOnUiThread()

Baughman answered 10/8, 2016 at 12:44 Comment(2)
i running that request method inside Doinbackground Only right?. how its running on UI threadFeatly
the dialog.dismiss() should be inside runOnUiThread(). It is method of Activity class.Baughman

© 2022 - 2024 — McMap. All rights reserved.