2016-08-01 37 views
9

1.Iam holt Masse der Daten von Server und Einfügen in der lokalen Datenbank während der Anmeldung in Android.Warum Android-Kreis-Fortschrittsdialog friert, wenn Datenbündel von Server zu lokaler Datenbank mit Retrofit

2.Für die Synchronisierung Zweck habe ich Retrofit Bibliothek verwendet, Synchronisieren und einfügen arbeiten fein.

Mein Problem: Während Syncing Bündel von Daten vom Server Mit Retrofit, Kreis Fortschritt Dialog Ersten Einfrieren.

Helfen Sie mir, wie Sie dieses Problem beheben können.

EDIT: 1

Called Retrofit Methode innerhalb Async Aufgabe, Still Kreis ProgressDialog Freeze-Erste

// Aufruf der Async Aufgabe

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

// AsyncTask METHODE

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(); 
           } 


          } 

         }); 

      } 
+3

Ist das nicht einfach, weil der Code im ui Thread ausgeführt wird? Wenn Sie es in einer asynchronen Aufgabe ablegen, sollten Sie es sofort wissen, wenn das das Problem ist. Retrofit bringt das Parsing immer in einen Hintergrund-Thread (AFAIK), aber Sie tun es irgendwie auch im Haupt-Thread ... – Fred

+0

aber ich habe diese Methode innerhalb Async-Task aufgerufen, aber immer noch Freeze, wenn Massen-Daten vom Server zu LocalDB holen :( – Kumar

+0

wie rufst du die 'execute' Methode deiner asyncTask an? Kannst du den Teil des Codes anzeigen? – Opiatefuchs

Antwort

2

Es gibt keinen guten Grund, eine synchrone Nachrüstung durchzuführen. In diesem Fall sollten Sie eine async call verwenden, die im Lieferumfang von Retrofit enthalten ist. Es ist sehr einfach und Sie können Ihre ProgressBar-Status mithilfe der Rückrufe verwalten.

IMO sollten Sie AsyncTask überhaupt nicht verwenden. Wenn Sie dieses überprüfen möchten, this, this und this.

Beispiel Codeumwandlung von Retrofit v1 Sync-Aufruf mit AsyncTask, nachzurüsten 2 Asynchron-Anruf, in api Klasse verwaltet und mit Otto Eventbus für 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("")); 
      } 
     }); 
    } 
} 

Sie erhalten eine Ereignisklasse müssen wickeln die Daten, die Sie erwarten, zurück von der API zu erhalten, zum Beispiel:

public class GetDataResponseEvent { 
    private final String data; 

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

    public String getData() { 
     return data; 
    } 
} 

Und als Beispiel für den Dienst von einem Activity Aufruf:

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); 
    } 

    // ... 
} 

Beachten Sie erneut, dass Sie auf Retrofit 2 aktualisieren und Otto verwenden müssen. Ich habe diese Implementierung erraten, so dass es nicht so funktioniert wie es ist, aber sollte eine gute Skizze sein, um das Gefühl davon zu bekommen.

+0

können Sie ein Code-Snippet für diese Lösung hinzufügen – Kumar

+0

okay, ich habe eine dded etwas –

+0

in Retrofit 1.9 können wir nicht hinzufügen Fortschrittsbalken ?, Mein Code Funktioniert gut, nur Progress Bar bekommen Freeze. !! – Kumar

3

Sie können pDialog.dismiss(); und Toast.makeText in doInBackground nicht verwenden.

Sie müssen dies in einer Methode tun, die Zugriff auf den UI-Thread wie onProgressUpdate() und onPostExecute() hat.

+0

hier Dismiss ruft innerhalb von doinbackground ist der Hauptgrund für dieses Problem? – Kumar

+0

Der Grund ist 'pDialog.dismiss();' und 'Toast.makeText'. Sie sollten das Ergebnis des Prozesses in 'doinbackground' an 'onPostExecute()' übergeben. Diesen Link finden Sie unter: http://stackoverflow.com/a/9671602/ 2335844 – HDehghani

+0

können Sie die vollständige Antwort zusammen mit meinem Code hinzufügen – Kumar

1

Dies ist Ihr RestInteface, wo Sie die Anrufe definieren

interface RestInterface { 

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

Dies ist die Implementierungsklasse zu machen, von wo aus Sie anrufen

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); 

    } 
} 

Diese Klasse im Format Ihrer empfangen werden sollte, Antwort

public class ModelResponse{ 

    String RouteId; 

    public String getRouteId(){ 
     return RouteId; 
    } 
} 

Jetzt von Ihrer Aktivität (oder Ihre bevorzugte Klasse), creat e ein Objekt von RestService, und rufen Sie die Methode getRoute() auf und übergeben Sie Ihre Abfragezeichenfolge und ein anonymes Callback-Objekt (2 Callback-Schnittstelle nachrüsten) als Parameter. Sie erhalten das Ergebnis im anonymen Callback-Objekt als Antwort. // später hinzugefügt Ihre Implementierungsklasse

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(); 
       } 
      }); 
    } 
} 
+0

wo ist meine Fortschrittsleiste? – Kumar

+0

Ich habe eine Implementierungsklasse am unteren Rand hinzugefügt. überprüfen Sie es – Debanjan

1

Es gibt zwei mögliche Ursachen für Probleme Einfrieren.

Zuerst: Ihre Anfrage läuft auf dem UI-Thread der Anwendung, was nicht empfohlen wird.

Zweite: Sie versuchen, Ihre App auf einem alten Gerät zu testen, das alte Prozessor hat.

Ich würde vorschlagen, Sie verwenden Retrofit eigene asynchrone Anfragen, die beschrieben wird here. Der Typ, der Ihnen gesagt hat, dass Sie dialog.dismiss() auf dem Hauptthread nicht anrufen sollten, ist richtig. Es kann auch Ihre App einfrieren. Here is a good example Wie vermeidet man es mit Methode runOnUiThread()

+0

Ich lief diese Anfrage Methode innerhalb Doinbackground Nur richtig ?. Wie läuft es auf UI-Thread – Kumar

+0

die dialog.dismiss() sollte innerhalb von runOnUiThread() sein. Es ist eine Methode der Aktivitätsklasse. – RexSplode