我正在使用Retrofit从REST API检索数据。首先,我在MainActivity上尝试了所有方法,并且效果很好。 然后,我将一些方法移至单例模式ClientApi类(这是正确的方法吗?我认为是正确的方法,但我做得不好) 现在,我看不到第一个OnCreate()方法的结果,我看到的只是“空”。 最终,如果我等待1秒钟并旋转手机以更改为横向(因此再次调用onCreate()),它将起作用。
public class MainActivity extends AppCompatActivity {
//UI components
TextView textViewHello;
//variables
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textViewHello = findViewById(R.id.text_hello);
ClientApi clientApi = ClientApi.getInstance();
Client client = clientApi.getClient(2);
String clientString = client.toString();
textViewHello.setText(clientString);
}
}
public class ClientApi {
private static final String TAG = "ClientApi";
private static final String API_BASE_URL = "https://my-json-server.typicode.com/";
private ClientsService clientsService;
public Client client = new Client();
private static ClientApi instance = null;
private ClientApi() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
clientsService = retrofit.create(ClientsService.class);
}
public static ClientApi getInstance() {
if (instance == null) {
instance = new ClientApi();
}
return instance;
}
public Client getClient(int clientId){
getClient1(clientId);
return client;
}
private void getClient1(int clientId) {
Call<Client> call = clientsService.getClient(clientId);
call.enqueue(new Callback<Client>() {
@Override
public void onResponse(Call<Client> call, Response<Client> response) {
if (response.isSuccessful()) {
client = response.body();
Log.d(TAG, "onResponse: response successfull, client: " + client);
} else {
Log.d(TAG, "onResponse: response not successfull: " + response.code());
}
}
@Override
public void onFailure(Call<Client> call, Throwable t) {
Log.d(TAG, "onFailure: " + t.getMessage());
}
});
}
}
预期结果是在首次启动应用程序时查看有关一个客户端的信息。但是直到我变成风景或肖像我才能看到它。
答案 0 :(得分:0)
调用clientApi.getClient(2)时,返回的立即值是 在您的ClientApi类中创建的客户端的新实例,因此,当再次调用OnCreate时,由于您的api已经完成,因此数据可用。
public Client client = new Client();
如果方法 private void getClient1(int clientId){...} 是异步的,则需要传递一个侦听器以接收您的API结果已返回数据
类似的东西
// create a interface to your response
public interface ApiResponse {
onResponse(Object response);
}
//update your getClient method
public void getClient(int clientId, ApiResponse apiResponse){
getClient1(clientId, apiResponse);
return client;
}
//update your getClient1 method and call the listener
private void getClient1(int clientId, ApiResponse apiResponse) {
Call<Client> call = clientsService.getClient(clientId);
call.enqueue(new Callback<Client>() {
@Override
public void onResponse(Call<Client> call, Response<Client> response) {
if (response.isSuccessful()) {
client = response.body();
// Call the listener
// apiResponse.onResponse(client)
Log.d(TAG, "onResponse: response successfull, client: " + client);
} else {
Log.d(TAG, "onResponse: response not successfull: " + response.code());
}
}
@Override
public void onFailure(Call<Client> call, Throwable t) {
Log.d(TAG, "onFailure: " + t.getMessage());
}
});
}
然后在MainActivity中调用您的api方法
Client client = clientApi.getClient(2, new ApiResponse() {
@Override()
public void onResponse(Object response) {
// response is your client data
}
});
答案 1 :(得分:0)
这是因为在使用call.enqueue()
时,您还没有意识到Retrofit在异步工作。第一次拨打以下电话时:
ClientApi clientApi = ClientApi.getInstance();
Client client = clientApi.getClient(2);
String clientString = client.toString();
textViewHello.setText(clientString);
client
中的 ClientApi
变量尚未用Retrofit调用中的数据填充。但是,当您等待1秒钟然后旋转设备时,您的client
变量已经充满了上一次Retrofit调用中的数据。因此,您实际上没有在TextView中获取当前数据。
您需要使用回调或将TextView传递给ClientApi
实例。
答案 2 :(得分:0)
您正在异步获取客户端,但是您正在像处理同步调用一样处理结果。 client
将在调用onResponse
之后保存您想要的值。我建议您创建一个私有侦听器,当client
的值更改时,该侦听器将通知您。
为此,我可以这样进行:
public interface OnClientFetchedListener{
void onClientFetched(Client client);
void onError(String errorMessage);
}
然后在ClientApi
类型的OnClientFetchedListener
中创建一个成员并添加一个setter。然后,在成功或出错时调用调用适当的方法。可以通过以下方式实现:
public class ClientApi {
private static final String TAG = "ClientApi";
private static final String API_BASE_URL = "https://my-json-server.typicode.com/";
private ClientsService clientsService;
public Client client = new Client();
private static ClientApi instance = null;
//our listener is just here
private OnClientFetchedListener listener;
//our setter is just here
public void setListener(OnClientFetchedListener listener){
this.listener = listener;
}
private ClientApi() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
clientsService = retrofit.create(ClientsService.class);
}
public static ClientApi getInstance() {
if (instance == null) {
instance = new ClientApi();
}
return instance;
}
public Client getClient(int clientId){
getClient1(clientId);
return client;
}
private void getClient1(int clientId) {
Call<Client> call = clientsService.getClient(clientId);
call.enqueue(new Callback<Client>() {
@Override
public void onResponse(Call<Client> call, Response<Client> response) {
if (response.isSuccessful()) {
client = response.body();
//invoke an appropriate method when on success
if(listener!=null)
{listener.onClientFetched(client);
}
Log.d(TAG, "onResponse: response successfull, client: " + client);
} else {
Log.d(TAG, "onResponse: response not successfull: " + response.code());
}
}
@Override
public void onFailure(Call<Client> call, Throwable t) {
Log.d(TAG, "onFailure: " + t.getMessage());
//invoke an appropriate method when on failure
if(listener!=null)
{listener.onError(t.getMessage());
}
}
});
}
}
然后,在onCreate
内部,将侦听器设置为ClientApi
对象,并侦听事件。您可以根据需要使活动/片段实现该接口。第一种方法可以通过以下方式实现:
public class MainActivity extends AppCompatActivity {
//UI components
TextView textViewHello;
//variables
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textViewHello = findViewById(R.id.text_hello);
ClientApi clientApi = ClientApi.getInstance();
//let's set our listener
clientApi.setListener(new OnClientFetchedListener(){
@Override
public void onClientFetched(Client client)
{
if(client!=null)
{
String clientString = client.toString();
textViewHello.setText(clientString);
}
}
@Override
public void onError(String errorMessage)
{
//log the error or something else
}
});
}
}
无论如何,这就是我如何做到这一点。解决方案太多...