尝试首先执行 Retrofit onResponse
Trying to get Retrofit onResponse executed first
我的 activity 中名为 AllStores
的列表仅包含空值。我需要这个列表,因为我想稍后填充我的 ListView。问题是因为我的回调最后执行了。
为了澄清,我在下面做了一个截图:
Link: 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;
}
但是我现在仍然得到相同的结果,请参见下面的屏幕截图:
link: http://i.imgur.com/GOGFXMR.png
屏幕截图看起来与上面的屏幕截图相同。
我认为您最好让 Retrofit 在其内部 HTTP 执行器上调用内部调用。这将涉及将您的 API 界面更改为如下内容:
public interface SubpriseAPI {
@GET("api/locations/get")
List<Store> listStores();
}
... 并包括 Retrofit 的任何相关配置以将反序列化处理为您的 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();
...
更新
我没有意识到你(显然)在使用 Retrofit 2。我有机会做了一些实验,这就是我想出的。
这是我的 app/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;
}
...最后,这是我的测试 activity:
public class 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>
作为 activity 的普通成员变量进行操作应该很简单。
希望对您有所帮助。
为了将结果从后台线程获取到主线程,我不得不使用 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
}
}
我的 activity 中名为 AllStores
的列表仅包含空值。我需要这个列表,因为我想稍后填充我的 ListView。问题是因为我的回调最后执行了。
为了澄清,我在下面做了一个截图:
Link: 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;
}
但是我现在仍然得到相同的结果,请参见下面的屏幕截图:
link: http://i.imgur.com/GOGFXMR.png
屏幕截图看起来与上面的屏幕截图相同。
我认为您最好让 Retrofit 在其内部 HTTP 执行器上调用内部调用。这将涉及将您的 API 界面更改为如下内容:
public interface SubpriseAPI {
@GET("api/locations/get")
List<Store> listStores();
}
... 并包括 Retrofit 的任何相关配置以将反序列化处理为您的 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();
...
更新
我没有意识到你(显然)在使用 Retrofit 2。我有机会做了一些实验,这就是我想出的。
这是我的 app/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;
}
...最后,这是我的测试 activity: public class 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>
作为 activity 的普通成员变量进行操作应该很简单。
希望对您有所帮助。
为了将结果从后台线程获取到主线程,我不得不使用 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
}
}