Android - Display loading bar when calling API with retrofit - java

In my app i am using retrofit 2 to retrieve data from a API. I have no problem about this. The problem is that i want to display a loading bar while this execution. The code is this
Call<MainInvestorProducts> call = apiInterface.getUseraccounts("Bearer "+bearerToken);
mkLoader.setVisibility(View.VISIBLE);
call.enqueue(new Callback<MainInvestorProducts>() {
#Override
public void onResponse(Call<MainInvestorProducts> call, Response<MainInvestorProducts> response) {
// If success response set the textViews
if (response.code() == 200) {
retrievedData = response.body();
//else display error message
}else if (response.code() == 401) {
Toasty.error(getApplicationContext(), getString(R.string.expired_token),Toasty.LENGTH_LONG).show();
finish();
}
}
#Override
public void onFailure(Call<MainInvestorProducts> call, Throwable t) {
}
});
mkLoader.setVisibility(View.GONE);
The problem is that mkloader is never show up.
My APIClient code
public class APIClient {
public static Retrofit retrofit = null;
public static Retrofit getClient(){
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();
retrofit = new Retrofit.Builder()
.baseUrl("https://api-test01.moneyboxapp.com")
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
return retrofit;
}
}
And this is an example of the Interface
#Headers({
"AppId: 3a97b932a9d449c981b595",
"Content-Type: application/json",
"appVersion: 5.10.0",
"apiVersion: 3.0.0"
})
#POST("/users/login")
Call<MainUserLogin> logInUser(#Body LoginBody loginBody);

Before calling the api you should start showing the loader (be sure that the api call is going to happen) and when once completed dismiss that

mkLoader.setVisibility(View.VISIBLE);
Call<MainInvestorProducts> call = apiInterface.getUseraccounts("Bearer "+bearerToken);
call.enqueue(new Callback<MainInvestorProducts>() {
#Override
public void onResponse(Call<MainInvestorProducts> call, Response<MainInvestorProducts> response) {
// If success response set the textViews
if (response.code() == 200) {
retrievedData = response.body();
//else display error message
}else if (response.code() == 401) {
Toasty.error(getApplicationContext(), getString(R.string.expired_token),Toasty.LENGTH_LONG).show();
finish();
}
}
#Override
public void onFailure(Call<MainInvestorProducts> call, Throwable t) {
mkLoader.setVisibility(View.GONE);
}
});
you just need to make the loader visibility to VISIBLE before calling the API and in case the api is succes or failure you set visibility to GONE

Related

How to convert BEGIN_OBJECT to BEGIN_ARRAY

i'm beginner of java, and i need some help, I had see many posts about, but not work they issues
I had json object from url like that
{
'history':[{
'id':2,
'name':'irine'},
{
'id':3,
'name':'karine'
}]
}
but i need
[
{
'id':2,
'name':'irine'},
{
'id':3,
'name':'karine'}
]
my ApiClient.java
public class ApiClient {
public static final String BASE_URL = "http://192.168.150.100";
public static Retrofit retrofit;
public static Retrofit getApiClient(final String authToken){
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient httpClient = new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request.Builder ongoing = chain.request().newBuilder();
ongoing.addHeader("Accept", "application/json;");
ongoing.addHeader("Authorization", authToken);
return chain.proceed(ongoing.build());
}
})//.addInterceptor(interceptor)
.build();
if (retrofit==null){
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(httpClient)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
getting response from url
call.enqueue(new Callback<List<Contact>>() {
#Override
public void onResponse(Call<List<Contact>> call, Response<List<Contact>> response) {
progressBar.setVisibility(View.GONE);
contacts=response.body();
if(contacts==null)
Snackbar.make(findViewById(R.id.lt_search), "Nothing found",Snackbar.LENGTH_LONG).show();
adapter = new Adapter(contacts, SearchActivity.this);
recyclerView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
#Override
public void onFailure(Call<List<Contact>> call, Throwable t) {
progressBar.setVisibility(View.GONE);
Log.d("GHaa ka sk aksjdk j", contacts.toString());
Toast.makeText(SearchActivity.this, "Error\n"+t.toString(), Toast.LENGTH_LONG).show();
}
});
how to convert object to array or clear word 'history' from object?
You have provided the wrong class for API response.You are getting the list object against a string key which might change(not known). So, you will have to use HashMap. The API response is in the form of HashMap<String,<List<Contact>>>. So in the code, you will have to use Callback<HashMap<String,List<Contact>>>() instead of Callback<List<Contact>>().
Then from the HashMap you can easily get the list using hashmap.get('key'). In your case, hashmap.get('history').
The right way to reselve this problem:
call.enqueue(new Callback<HashMap<String,List<Contact>>>() {
#Override
public void onResponse(Call<HashMap<String, List<Contact>>> call, Response<HashMap<String, List<Contact>>> response) {
HashMap<String, List<Contact>> history=response.body();
contacts= new ArrayList<>(history.get("hitory"));
Log.d(TAG, contacts.toString());
progressBar.setVisibility(View.GONE);
//contacts=response.toString();
Log.d(TAG,response.toString());
if(contacts==null)
Snackbar.make(findViewById(R.id.lt_search), "Nothing found",Snackbar.LENGTH_LONG).show();
adapter = new Adapter(contacts, SearchActivity.this);
recyclerView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
#Override
public void onFailure(Call<HashMap<String, List<Contact>>> call, Throwable t) {
progressBar.setVisibility(View.GONE);
//Log.d("GHaa ka sk aksjdk j", contacts.toString());
Toast.makeText(SearchActivity.this, "Error\n"+t.toString(), Toast.LENGTH_LONG).show();
}
});

Can not stop retrofit sending

I use retrofit and OkHttp3 library to send some messages to a server and set its as below :
okClient = new OkHttpClient.Builder()
.connectTimeout(15, TimeUnit.SECONDS)
.readTimeout(15, TimeUnit.SECONDS)
.writeTimeout(15,TimeUnit.SECONDS)
.addInterceptor(interceptor)
.build();
When I want to send a large message(which, for example, it takes about 2 minutes), Retrofit sends my file completely, and after 2 minutes, I get the TimeOut message. If I expect to stop sending after 15 seconds and show me the Error message.
Is there a specific item that I must comply with? Please guide me.
Or suggest me a standard way to break this operation after 15 second.
mycode:
class RetrofitFactory {
private static final RetrofitFactory INSTANCE = new RetrofitFactory();
public static RetrofitFactory getInstance() {
return INSTANCE;
}
public OkHttpClient getOkHttp()
{
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
okClient = new OkHttpClient.Builder()
.connectTimeout(15, TimeUnit.SECONDS)
.readTimeout(15, TimeUnit.SECONDS)
.writeTimeout(15,TimeUnit.SECONDS)
.addInterceptor(new GzipRequestInterceptor())
.addInterceptor(interceptor)
.build();
return okClient;
}
public myInterface getlimit()
{
if (retrofit == null) {
OkHttpClient okClient = getOkHttp();
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
retrofit = new Retrofit.Builder()
.client(okClient)
.baseUrl(BuildConfig.BASEURL)
.addConverterFactory(JacksonConverterFactory.create(objectMapper))
.build();
}
return retrofit.create(myInterface.class);
}
}
public interface myInterface{
#POST("api/ReadingApi/Something")
Call<Something> DoReading(
#Body List<Something> list,
#Header("Authorization") String auth);
}
Call<DoReadResult> x = RetrofitFactory.getInstance().getlimit().DoReading(
data, "Something");
response = x.execute();
Update:
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
implementation 'com.squareup.retrofit2:converter-jackson:2.5.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0'
As you said you are using retrofit , so you need to cancel your call easily with retrofit Call :
Call<ResponseBody> call =
uploadService.uploadSomething(fileUrl);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
Log.d(TAG, "request success");
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.e(TAG, "request failed");
}
});
}
call.cancel();
with call.cancel(); you can cancel your request.
See more here :
Retrofit Cancel Request

Proxy Authentication Required, Retrofit

Getting this error when make api call in retrofit
Response{protocol=http/1.1, code=407, message=Proxy Authentication
Required, url=http://example.com/test.xml}
below was my api call.
private void showProxies() {
serviceCall = apiService.listOfServers();
serviceCall.enqueue(new Callback<ServerListModel>() {
#Override
public void onResponse(Call<ServerListModel> call, Response<ServerListModel> response) {
if (response.body() != null) {
ArrayList<Proxies> proxyArrayList = response.body().proxiesArrayList;
showProxyDialog(proxyArrayList);
}
else
Toast.makeText(BrowserActivity.this, "Server 407 error.", Toast.LENGTH_SHORT).show();
}
#SuppressLint("LongLogTag")
#Override
public void onFailure(Call<ServerListModel> call, Throwable t) {
Log.e(TAG, t.toString());
}
});
}
you have add proxy to you Retrofit object
java.net.Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort));
OkHttpClient client = new OkHttpClient.Builder().proxy(proxy).build();
Retrofit.Builder builder = new Retrofit.Builder().client(client);
Retrofit retrofit = builder.build();
In my case, I was connected to the proxy network this issue is not related to retrofit.

Retrofit 2 returns HTML instead of JSON

I am making a POST Request to an ASP.NET API using Retrofit 2, I am getting an HTML in response instead of JSON. If I change the target URL and call a different API and get JSON response
Here is my API interface
#POST("PosLogin")
Call<CinekinRequest> login();
Rest Manager
public static final String BASE_URL = "******************";
private API homeApi;
public API getAPi() {
if (homeApi == null) {
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(logging);
Gson gson = new GsonBuilder()
.setLenient()
.create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.client(httpClient.build())
.build();
homeApi = retrofit.create(API.class);
}
return homeApi;
}
Executing my login()
public void login(final Context context, CinekinRequest login){
Log.e("login", "starting");
Call call = manager.getAPi().login( );
call.enqueue(new Callback<CinekinRequest>() {
#Override
public void onResponse(Call<CinekinRequest> call, Response<CinekinRequest> response) {
Toast.makeText(context, "Success " + response.message(), Toast.LENGTH_SHORT).show();
Log.e("res", "success");
}
public void onFailure(Call<CinekinRequest> call, Throwable t) {
Toast.makeText(context, "error: " + t.getMessage(), Toast.LENGTH_LONG).show();
Log.e("error", t.getMessage());
}
});
}
Please add statement below in retrofit onResponse
if (response.isSuccessful()) {
// Do something
} else {
// Do something
}
or if you want only accept response 200
if (response.code() == 200) {
// Do something
} else {
// do something
}

Retrofit enqueue doesn't work but execute work

I'm using com.squareup.retrofit2:retrofit:2.2.0
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(logging);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://localhost:9000")
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient.build())
.build();
final UserService service = retrofit.create(UserService.class);
Call<User> userCall = service.createUser(user)
Here is the problem: when I run the execute it make REST API request but when I use enqueue it does nothing (no exception, no log)
userCall.execute(); //this work
//this does not work
userCall.enqueue(new Callback<User>() {
#Override
public void onResponse(Call<User> call, Response<User> response) {
// no response
}
#Override
public void onFailure(Call<User> call, Throwable t) {
//nothing here
}
});
Well,
The issue was because I was using an emulator and try to call the localhost however, it turn out if you want call the localhost you have to use this ip 10.0.2.2
The execute works because I was running as unit test but when it runs enqueue I think it need to run on android platform.
refer to this
https://developer.android.com/studio/run/emulator.html#networkaddresses
How to get the Android Emulator's IP address?
You can try this full Answer Link
Here is the shortest code snippest.
private void emailLoginRequest() {
LoginService loginService = ApiFactory.createService(LoginService.class);
Call<JsonObject> call = loginService.login(edtEmail.getText().toString(),edtPassword.getText().toString(),mDeviceType,mDeviceToken);
call.enqueue(new Callback<JsonObject>() {
#Override
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
hideProgressDialog();
if (response.isSuccessful()) {
LOGD(TAG, "onResponse 0: " + response.body().toString());
LoginResponse loginResponse = new Gson().fromJson(response.body().toString(), LoginResponse.class);
System.out.println("+++ get message >> " + loginResponse.getMessage());
int status = loginResponse.getStatus();
}else {
LOGD(TAG, "response fail 0: " + response.body());
}
}
#Override
public void onFailure(Call<JsonObject> call, Throwable t) {
hideProgressDialog();
LOGD(TAG, "onFailure: " + t.getMessage());
}
});
}
put your code as this:
userCall.enqueue(new Callback<User>() {
#Override
public void onResponse(Call<User> call, Response<User> response) {
Toast.makeText(this, "in response", Toast.LENGTH_SHORT).show();
}
#Override
public void onFailure(Call<User> call, Throwable t) {
Toast.makeText(this, "in response", Toast.LENGTH_SHORT).show();
}
});
Now based on method call you will get toast if its in response toast will be "In response" don't forget write youractivity name before this like : MainActivity.this
see this
retrofit can be called by 2 methods separately one is synchronous and another way is asynchronous.
enqueue is an asynchronous way where it does not wait for a response and proceed. here you need to handle Call separately to load UI later.
Execute is asynchronously call rest api and wait until get response and process it.
choice wisely

Categories