to invoke interface method 'retrofit2.Call on a null object reference - retrofit2

how can i solve null object while sending post request
error says
to invoke interface method 'retrofit2.Call com.itgrepnet.foodbundle.remote.UserService.addUser(com.itgrepnet.foodbundle.model.User)' on a null object reference
in AddUserActivity
btnSubmit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
addNewUser();
}
private void addNewUser() {
User u = new User();
u.setFirstname(first_name.getText().toString());
u.setLastname(last_name.getText().toString());
u.setEmail(email.getText().toString());
u.setPassword(password.getText().toString());
Call<User> call = userService.addUser(u);
call.enqueue(new Callback<User>() {
#Override
public void onResponse(Call<User> call, Response<User> response) {
if (response.isSuccessful()) {
Toast.makeText(getApplicationContext(), "User Created Successfully!", Toast.LENGTH_LONG).show();
}
}
#Override
public void onFailure(Call<User> call, Throwable t) {
Log.e("Error: ", t.getMessage());
}
});
}
});
UserService.java
#POST("user/")
Call<User> addUser(#Body User user);
RetrofitClient.java
public class RetrofitClient {
private static Retrofit retrofit = null;
public static Retrofit getClient(String url) {
if (retrofit == null) {
retrofit = new Retrofit.Builder().baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}

Related

OKHttp DNS lookup asynchronously

public class OkHttpDns implements Dns {
#NotNull
#Override
public List<InetAddress> lookup(#NotNull String hostname) throws UnknownHostException {
MyLookUpUtility.getInstance.lookup(hostname, new MyLookUpUtility.lookupCallback()
{
#Override
public void onlookupResponseSuccess(JSONObject nslookupResponseJSON) {
Log.d("LookupResponse", nslookupResponseJSON.toString());
}
#Override
public void onlookupResponseFailure(String errCode) {
Log.d("LookupResponse", "Error Code : "+errCode);
}
});
}
}
In the above code, lookup method of DNS interface of OKHttp wants to return immediately. But my custom NSLookupUtility is an asynchronous call and I will have the ip address of the hostname only after a while. How to solve this problem? how to make the synchronous call to wait for the asynchronous call within it ?
Take a look at CompletableFuture. You’ll create an instance in lookup(), kickoff the async lookup, and then call future.get(). When your async call completes, call future.complete().
#Override
public List<InetAddress> lookup(#NotNull String hostName) throws UnknownHostException {
completableFuture = new CompletableFuture<>();
performLookUp(hostName);
try {
String ipAddress = completableFuture.get();
if (ipAddress != null) {
List<InetAddress> inetAddresses = Arrays.asList(InetAddress.getAllByName(ipAddress));
return inetAddresses;
}
} catch (ExecutionException e) {
Log.d(TAG, "Error : ExecutionException : "+e );
e.printStackTrace();
} catch (InterruptedException e) {
Log.d(TAG, "Error : InterruptedException : "+e );
e.printStackTrace();
}
return Dns.SYSTEM.lookup(hostName);
}
private void performLookUp(#NotNull String hostName) {
MyUtiluty.getInstance().lookup(hostName,
new MyCallBack() {
#Override
public void onSuccess(String ip) {
completableFuture.complete(ip);
}
#Override
public void onFailure(String errCode) {
completableFuture.complete(null);
}
});
}

Why my variables are set to null after i volley call is succeed

I do not why my private variable values are getting to null after the Volley request
When i am printing the values in onResponse, i am getting required values, but after volley request is completed, I am getting null.
ListView userListView;
StringRequest stringRequest=null;
ProgressDialog progressDialog;
private String[] strUsername;
private String[] strUserItems;
private String[] strUserImagePaths;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user_listing);
userListView=findViewById(R.id.userListView);
progressDialog=new ProgressDialog(this);
StrictMode.setThreadPolicy((new StrictMode.ThreadPolicy.Builder().permitNetwork().build()));
displayUserListing();
UserListCustomViewAdapter viewAdapter=new UserListCustomViewAdapter(this,strUsername,strUserImagePaths,strUserItems);
userListView.setAdapter(viewAdapter);
}
private void displayUserListing()
{
progressDialog.setMessage("Getting User List...");
progressDialog.show();
stringRequest=new StringRequest(
Request.Method.GET, Constants.URL_GetUserList, new Response.Listener<String>()
{
#Override
public void onResponse(String response)
{
progressDialog.dismiss();
try {
Log.d("first","before");
JSONArray jsonObj=new JSONArray(response);
strUsername=new String[jsonObj.length()];
strUserItems=new String[jsonObj.length()];
strUserImagePaths=new String[jsonObj.length()];
String str=null;
for(int i=0;i<jsonObj.length();i++)
{
JSONObject jsonObject=jsonObj.getJSONObject(i);
strUsername[i]=jsonObject.getString("user_name");
strUserItems[i]=jsonObject.getString("user_item");
strUserImagePaths[i]=jsonObject.getString("user_image_path");
str+=strUsername[i];
}
Log.d("first","after"+str);
}catch (Exception e)
{
e.printStackTrace();
}
}
}, new Response.ErrorListener()
{
#Override
public void onErrorResponse(VolleyError error)
{
progressDialog.hide();
Log.d("myerror","I got some error");
NetworkResponse networkResponse = error.networkResponse;
Log.d("myerror1",error.getMessage());
// Toast.makeText(getApplicationContext(),error.getMessage().toString(),Toast.LENGTH_LONG).show();
}
})
{
#Override
protected Map<String, String> getParams() throws AuthFailureError
{
Map<String,String> params=new HashMap<String,String>();
params.put("struserid","1");
//params.put("serviceid","1");
return params;
}
};
RequestHandler.getInstance(this).addToRequestQueue(stringRequest);
}
I think you are using your variables before initializing it. Call the adapter after you parsing value.

Android Don't execute anything until location variable exists

Goodmorning,
I've tried to implement the method that request permission first and than execute something but without success ...
Here is my MainActivity code:
public class MainActivity extends AppCompatActivity {
public static String latitudineCorrente = ""; //current Latitude
public static String longitudineCorrente = ""; //current Longitude
private SharedPreferences sharedPreferences; //shared preferences
private SharedPreferences.Editor mEditor; // shared preferences editor
/* Variable for getting location */
private FusedLocationProviderClient fusedLocationProviderClient;
private LocationRequest locationRequest;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String appLanguage = "ita";
LanguageUtil.setAppLanguage(getApplicationContext(), appLanguage);
/* .... other code.... */
sharedPreferences = this.getSharedPreferences("appname", MODE_PRIVATE);
mEditor = sharedPreferences.edit(); // set edit sharedpreferences
richiamaPermessi(); //permission request
requestLocationUpdates(); // function requestlocationupdates();
CaricamentoInizialeApplicazione(); // function for presetting configurations
}
private void CaricamentoInizialeApplicazione() {
boolean configIniziale = sharedPreferences.getBoolean("configurazioneinizialeok", false);
if(!configIniziale)
{
/* can't execute this because Double.parseDouble(this.latitudineCorrente), Double.parseDouble(this.longitudineCorrente) */
ApiMarkers.getMarkers(MainActivity.this, 0, 400,
Double.parseDouble(this.latitudineCorrente), Double.parseDouble(this.longitudineCorrente),
0, 0,0,1, 0,0,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
/* response elaborations */
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
dialog.dismiss();
Toast.makeText(MainActivity.this, "" + error.getMessage(), Toast.LENGTH_LONG).show();
error.printStackTrace();
}
});
mEditor.putBoolean("configurazioneinizialeok", true);
mEditor.commit();
}
}
/* Function for requist location updates */
public void requestLocationUpdates() {
if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) ==
PermissionChecker.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) ==
PermissionChecker.PERMISSION_GRANTED) {
fusedLocationProviderClient = new FusedLocationProviderClient(this);
locationRequest = new LocationRequest();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setFastestInterval(1500);
locationRequest.setInterval(3000);
fusedLocationProviderClient.requestLocationUpdates(locationRequest, new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
super.onLocationResult(locationResult);
mEditor = sharedPreferences.edit();
mEditor.putString("latitudine", String.valueOf(locationResult.getLastLocation().getLatitude()));
mEditor.putString("longitudine", String.valueOf(locationResult.getLastLocation().getLongitude()));
MainActivity.latitudineCorrente = String.valueOf(locationResult.getLastLocation().getLatitude());
MainActivity.longitudineCorrente = String.valueOf(locationResult.getLastLocation().getLongitude());
Log.d("coordinate", "MAIN ACTIVITY: Latitudine: " + MainActivity.latitudineCorrente + "/"
+ "Longitudine: " + MainActivity.longitudineCorrente);
}
}, getMainLooper());
} else richiamaPermessi();
}
/* Function for requesting access */
public void richiamaPermessi()
{
Permissions.check(this, new String[] { Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION},
"Permessi di locazione obbligatori per determinare la propria posizione!",
new Permissions.Options().setSettingsDialogTitle("Avviso").setRationaleDialogTitle("Permessi locazione"),
new PermissionHandler() {
#Override
public void onGranted() {
requestLocationUpdates();
}
#Override
public void onDenied(Context context, ArrayList<String> deniedPermissions) {
super.onDenied(context, deniedPermissions);
richiamaPermessi();
}
});
}
}
The problem is executing function ApiMarkers.getMarkers(.... with latitude and longitude filled ...) but can't execute because latitude and longitude are not loaded... I spent two nights without solution :(
Thanks for any help!
Cristian

RxJava subscribe onNext is not called when adding element asynchronously

I have a Observable like this
Observable<String> gitHubRepoModelObservable;
I have this code
repoNames = new ArrayList<String>();
gitHubRepoModelObservable = Observable.fromIterable(repoNames);
repoNames.add("Hello");
gitHubRepoModelObservable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<String>() {
#Override
public void onSubscribe(Disposable d) {
}
#Override
public void onNext(String s) {
System.out.println(s);
}
#Override
public void onError(Throwable e) {
}
#Override
public void onComplete() {
}
});
repoNames is just a list of string. When I am adding a string "hello" manually the onNext is getting called but when I am adding string from a API call like bellow
call.enqueue(new Callback<List<GitHubRepoModel>>() {
#Override
public void onResponse(Call<List<GitHubRepoModel>> call, Response<List<GitHubRepoModel>> response) {
for (GitHubRepoModel repo : response.body()) {
repoNames.add(repo.getName());
}
}
#Override
public void onFailure(Call<List<GitHubRepoModel>> call, Throwable t) {
}
});
I am adding strings from the API into the repoNames the "onNext" is not getting called.
I have seen
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
can be added while initializing retrofit but I want to better understand the rxjava so in this experiment it is not working.
Please help!
It can't not be work.
When you create you api request and try subscribe you list is emty, so Observable does not work.
You need to create Observable such, that your subcribe will run your request!
Observable<String> gitHubRepoModelObservable = Observable.create(
new Observable.OnSubscribe<String>() {
#Override
public void call(final Subscriber<? super String> sub) {
call.enqueue(new Callback<List<GitHubRepoModel>>() {
#Override
public void onResponse(Call<List<GitHubRepoModel>> call, Response<List<GitHubRepoModel>> response) {
for (GitHubRepoModel repo : response.body()) {
sub.onNext(repo.getName()); //send result to rx
}
sub.onCompleted();
}
#Override
public void onFailure(Call<List<GitHubRepoModel>> call, Throwable t) {
}
});
}
}
);
gitHubRepoModelObservable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<String>() {
#Override
public void onNext(String s) {
System.out.println(s);
}
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable e) {
}
});
Why would onNext get called if you are just adding element to plain List?
In the first example you are seeing onNext being called because modified list is passed through the stream during subscribe.
Create Subject ex. PublishSubject and pass list to Subject.onNext in onResponse, subscribe to it and you will get what you want.
Second option is adding RxJava2CallAdapterFactory and return Observable<Response<List<GithubRepoModel>>>. This way you don't need to create stream yourself.

How to combine Retrofit 2 with Realm and RxJava

I want to save retrofit responses to realm on the background thread then pass it to the UI Thread, but its a bit tricky since Realm is very touchy with threads. so the code would look like something like this, please submit your edits to all better solutions :)
restApi.userRealmList()
.doOnNext(userRealmModels -> {
if (userRealmModels != null){
mRealm = Realm.getInstance(mContext);
mRealm.asObservable()
.map(realm -> mRealm.copyToRealmOrUpdate(userEntity))
.subscribe(new Subscriber<Object>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable e) {
e.printStackTrace();
}
#Override
public void onNext(Object o) {
Log.d("RealmManager", "user added!");
}
});
}})
.map(userEntityDataMapper::transformAll)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<List<User>>() {
#Override
public void onCompleted() {
hideViewLoading();
}
#Override
public void onError(Throwable e) {
hideViewLoading();
showErrorMessage(new DefaultErrorBundle((Exception) e));
showViewRetry();
}
#Override
public void onNext(List<User> users) {
showUsersCollectionInView(users);
}
});
You code doesn't look like it can compile? E.g. what is userEntity. Also your copyToRealmOrUpdate isn't inside an transaction, so that will also crash, but it has nothing to do with threads.
If you want to save some data as a side-effect before sending it to the UI, you should be able to do the following:
restApi.userRealmList()
.doOnNext(userRealmModels -> {
if (userRealmModels != null) {
Realm realm = Realm.getInstance(mContext);
realm.beginTransaction();
realm.copyToRealmOrUpdate(userRealmModels);
realm.commitTransaction();
realm.close();
}})
.map(userEntityDataMapper::transformAll)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<List<User>>() {
#Override
public void onCompleted() {
hideViewLoading();
}
#Override
public void onError(Throwable e) {
hideViewLoading();
showErrorMessage(new DefaultErrorBundle((Exception) e));
showViewRetry();
}
#Override
public void onNext(List<User> users) {
showUsersCollectionInView(users);
}
});

Resources