2015-12-17 4 views
0

Мой список в моей деятельности под названием AllStores содержит всего лишь null. Мне нужен этот список, потому что я хочу позже заполнить свой ListView. Проблема вызвана тем, что мой обратный вызов выполняется как последний.Пытается получить Дооснащение onResponse выполнено

Для уточнения я сделал скриншот ниже:

Ссылка: http://i.imgur.com/bIkWjld.png

скриншот также говорит, что я на самом деле хочу. Чтобы добиться этого, я попробовал его с помощью AsyncTask. Однако это не сработало, как вы можете видеть на скриншоте.

Вот код:


EDIT 2,0 я изменил свое getSubprise() метод становятся синхронными и использованием AsyncTask

AllStores.java:

protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    Response<List<Store>> subprises = new StoreService().getSubprises(); 
    System.out.println("AllStores (Activity) - subprise " + subprises); 
} 

StoreService.java :

 public Response<List<Store>> getSubprises() { 
     new LongOperation().execute(""); 
     System.out.println("getStores (StoreService.java) value "+ getStores()); 
     return getStores(); 
    } 

    private class LongOperation extends AsyncTask<String, Void, Response<List<Store>>> { 

     @Override 
     protected Response<List<Store>> doInBackground(String... params) { 
      System.out.println("doInBackground executed second"); 
      try { 
       Call<List<Store>> call = subpriseAPI.listStores(); 
       stores=call.execute(); 
       Iterator it=stores.body().iterator(); 
//    while(it.hasNext()) 
//     System.out.println(((Store)it.next()).getSTREET()); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
      return stores; 
     } 

     @Override 
     protected void onPreExecute() { 
      //Can't put the call here because this is the main thread 
      System.out.println("onPreExecute first"); 
     } 

     @Override 
     protected void onPostExecute(Response<List<Store>> result) { 
      //Can't put the call here because this is the main thread 
      setStores(stores); 
     } 
    } 

    public Response<List<Store>> getStores() { 
     return stores; 
    } 

    public void setStores(Response<List<Store>> stores) { 
     this.stores = stores; 
    } 

Однако сейчас я все еще получаю тот же результат, увидеть скриншот ниже:

ссылка: http://i.imgur.com/GOGFXMR.png

скриншот выглядит так же, как на скриншоте сверху.

+1

Вы должны действительно прочитать некоторые документы о асинхронном коде и обратных вызовах. Полная асинтеза является бесполезной из-за асинхронного вызова очереди. Ваши загруженные данные будут доступны при вызове onresponse, поэтому есть смысл обновить ui. –

+0

@Andre Classen Да, что вы сказали, действительно так. Но я отредактировал мой вопрос, не могли бы вы ответить на него сейчас :)? – superkytoz

+0

Теперь вы изменили вызов очереди, который был асинхронным, на синхронный вызов execeute. Исключение говорит об этом «NetworkOnMainThreadException». Сетевой вызов должен выполняться в фоновом потоке. Например. вызов doInBackground() в asyncTask. –

ответ

1

Чтобы получить результат из фоновой нити в основной поток, мне пришлось использовать AsyncTask.get(). Используя это, я мог видеть значение в моей переменной stores вместо нулевого значения.

Ниже вы можете увидеть мой код для тех, кто хочет видеть его:

@TargetApi(Build.VERSION_CODES.HONEYCOMB) 
public Response<List<Store>> getSubprises() throws IOException, ExecutionException, InterruptedException { 
    LongOperation longOperation = new LongOperation(); 
    longOperation.execute(""); 
    stores = longOperation.get(); 
    return stores; 
} 

private class LongOperation extends AsyncTask<String, Void, Response<List<Store>>> { 
    @Override 
    protected Response<List<Store>> doInBackground(String... params) { 
     //System.out.println("doInBackground executed second"); 
     try { 
      Call<List<Store>> call = subpriseAPI.listStores(); 
      stores=call.execute(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     return stores; 
    } 

    @Override 
    protected void onPreExecute() { 
     //Can't put the call here because this is the main thread 
     //System.out.println("onPreExecute first"); 
    } 

    @Override 
    protected void onPostExecute(Response<List<Store>> result) { 
     //Can't put the call here because this is the main thread 
    } 
} 
0

Я думаю, вам лучше позволить Retrofit вызывать вызовы внутри своей внутренней HTTP-исполнительницы. это предполагает изменение вашего интерфейса API, чтобы что-то вроде этого:

public interface SubpriseAPI { 
    @GET("api/locations/get") 
    List<Store> listStores(); 
} 

... включая любую соответствующую конфигурацию для дооснащения для обработки десериализации в ваш Store типа.

Однако, если вы хотите сами вызвать вызовы, вы можете подумать о том, чтобы разместить собственный экземпляр исполнителя (или, тем не менее, вы хотите запустить рабочие потоки), что-то вроде этого (не эта точная реализация, но вы должны получить идею):

class StoreService { 
... 
private final ExecutorService executorService = Executors.newCachedThreadPool(); 
... 
public Response<List<Store>> getSubprises() { 
    executorService.submit(new Callable<List<Store>>() { 
      @Override 
      public List<Store> call() throws Exception { 
       final Call<List<Store>> call = subpriseAPI.listStores(); 

       try { 
        if(stores == null) { 
         stores = new ArrayList<>(); 
        } else { 
         stores.clear(); 
        } 

        stores.addAll(call.execute()); 

        System.out.println("stores "+ stores); 

       } catch (IOException e) { 
        e.printStackTrace(); 
       } 
      } 
     }).get(); 
... 

UPDATE

я не знал, что вы (видимо) с использованием Дооснащение 2. Я имел возможность экспериментировать немного, и это то, что я придумал.

здесь соответствующие зависимости у меня в приложение/build.gradle:

compile 'com.squareup.retrofit:retrofit:2.0.0-beta2' 
compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2' 

... вот мой API-интерфейс:

public interface Api { 
    @Headers("Accept: application/json") 
    @GET("/v2/567595ad0f0000ea23315d02") 
    public Call<List<Widget>> widgets(); 

} 

... вот простой DTO я буду разбирать некоторые JSON в:

public class Widget { 
    public String value; 
} 

...и, наконец, вот мой тест активность: общественного класса Retrofit2TestActivity расширяет AppCompatActivity {

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

     final Api mockyApi = new Retrofit.Builder() 
      .baseUrl("http://www.mocky.io") 
      .addConverterFactory(GsonConverterFactory.create()) 
      .build() 
      .create(Api.class); 

     mockyApi.widgets().enqueue(new Callback<List<Widget>>() { 
      @Override 
      public void onResponse(Response<List<Widget>> response, Retrofit retrofit) { 
       if(response.isSuccess()) { 
        Log.d(Retrofit2TestActivity.class.getName(), "## widgets.size() == " + response.body().size()); 
       } else { 
        Log.d(Retrofit2TestActivity.class.getName(), String.format("## response was NOT successful [%d]", response.code())); 
       } 
      } 

      @Override 
      public void onFailure(Throwable t) { 
       Log.d(Retrofit2TestActivity.class.getName(), String.format("## response was NOT successful [%s]", t.getMessage())); 
      } 
     }); 
    } 

} 

, очевидно, вы должны заменить мой Widget для Store типа. кроме того, манипулирование List<Store> в качестве обычной переменной-члена вашей деятельности должно быть простым.

Я надеюсь, что это помогло.

+0

Я попробую это после того, как спал. Сейчас в моей стране три часа ночи. – superkytoz

+0

@hsi Если я использую 'List listStores();' в SubpriseAPI.java, то я получаю следующую ошибку: 'Невозможно создать адаптер вызова для java.util.List ' – superkytoz

Смежные вопросы