我正在使用Retrofit从REST API检索数据。首先,我在主活动上尝试了所有内容,效果很好。然后,我将一些方法移动到单例模式 ClientApi 类(这是正确的方法吗?我认为是的,但我做得不好(现在,我看不到第一个OnCreate((方法的结果,我看到的只是"null"。最后,如果我等待 1 秒钟并旋转手机以更改为横向(因此再次调用 Create(( (,它可以工作。
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());
}
});
}
}
预期结果是在首次启动应用时查看有关一个客户端的信息。但是在我更改为横向或纵向之前,我看不到它。
当 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());
}
});
}
然后在您的主活动中调用您的 api 方法
Client client = clientApi.getClient(2, new ApiResponse() {
@Override()
public void onResponse(Object response) {
// response is your client data
}
});
这是因为您没有意识到改造在使用call.enqueue()
时是异步工作的。首次调用以下内容时:
ClientApi clientApi = ClientApi.getInstance();
Client client = clientApi.getClient(2);
String clientString = client.toString();
textViewHello.setText(clientString);
ClientApi
client
变量尚未填充来自改造调用的数据。但是,当您等待 1 秒钟然后旋转设备时,您的client
变量已经填充了上一次 Retrofit 调用的数据。因此,您实际上没有在文本视图中获取当前数据。
您需要使用回调或将 TextView 传递给ClientApi
实例。
您正在异步获取客户端,但您正在处理结果,就好像它是同步调用一样。 client
将在调用onResponse
后保存所需的值。我可以建议你创建一个私人侦听器,当client
的值发生变化时会通知你。
为此,我可以这样进行:
public interface OnClientFetchedListener{
void onClientFetched(Client client);
void onError(String errorMessage);
}
然后在ClientApi
类型为 OnClientFetchedListener
中创建一个成员并添加一个资源库。然后在成功或错误时调用 invoke 适当的方法。这可以通过以下方式实现:
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
}
});
}
}
无论如何,这就是我怎么能做到这一点的。有太多的解决方案...