![](/img/trans.png)
[英]How can I call the retrofit service that is nested and retrieve the data correctly? [retrofit2]
[英]How to fix: The first time OnCreate() is called, I can't retrieve data from Retrofit Concrete Class
我正在使用 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());
}
});
}
}
預期的結果是在第一次啟動應用程序時看到有關一個客戶端的信息。 但是直到我更改為橫向或縱向我才能看到它。
當調用 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
}
});
這是因為您沒有意識到在使用call.enqueue()
時 Retrofit 是異步工作的。 當您第一次調用以下內容時:
ClientApi clientApi = ClientApi.getInstance();
Client client = clientApi.getClient(2);
String clientString = client.toString();
textViewHello.setText(clientString);
ClientApi
client
變量尚未填充來自 Retrofit 調用的數據。 但是當您等待 1 秒然后旋轉設備時,您的client
變量已經填充了來自先前 Retrofit 調用的數據。 因此,您實際上並未在 TextView 中獲取當前數據。
您需要使用回調或將您的 TextView 傳遞給您的ClientApi
實例。
您正在異步獲取您的客戶端,但您正在處理結果,就好像它是一個同步調用一樣。 client
將在onResponse
后onResponse
您想要的值。 我可以建議您創建一個私人偵聽器,當client
的值發生變化時會通知您。
為此,我可以這樣進行:
public interface OnClientFetchedListener{
void onClientFetched(Client client);
void onError(String errorMessage);
}
然后在ClientApi
中創建一個OnClientFetchedListener
類型的成員並添加一個 setter。 然后在成功或錯誤時調用 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
}
});
}
}
無論如何,這就是我能做到的。 解決方法太多了...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.