Android: getContext().getContentResolver() sometimes gets NullPointerException - java

I want to ask why we get this annotation:
Method invocation getContext.getContentResolver() may produce
NullPointerException
Why is it there and not in other parts of program Fragment/Activity? That approach has been used in tutorial made by Google - here is link for ContentProvider code https://github.com/udacity/Sunshine-Version-2/blob/sunshine_master/app/src/main/java/com/example/android/sunshine/app/data/WeatherProvider.java even if you create an aplication with just a blank activity and put that method in a newly created ContentProvider it is there.
Should we use getContext().getContentResolver().notifyChange(uri, null);outside ContentProvider getting the uri passed and then after the update/insert/delete is finished notifyChange? or maybe we can fix it somehow?

If you look in the source of ContentProvider (just hold SHIFT and click on the classname in Android Studio) then you will find that the implementation is holding an object of type Context as mContext.
Your solution is just the same, which means if mContext of ContentProvider is null, your reference will also be null. So there is no need for this.
To help you out, this is just a warning of your IDE if make such a construct yourself. But in this case there will always be context, because the ContentProvider is generated by your system. To avoid the error in your IDE just write #SuppressWarnings("ConstantConditions") above your class definition like:
...
#SuppressWarnings("ConstantConditions")
public class NoteProvider extends ContentProvider {
...

If you can make sure that getContext() can never be null then you can simply ignore this warning. I think the warning even disappears of you just check for null:
if (getContext() != null) {
getContext().getContentResolver();
}
You just have to keep in mind the code won't be executed if getContext() is null.
Cheers
edit:
Be careful with the answer #Shivani Gupta gave you, because you could get different contexts. See: Difference between getContext() , getApplicationContext() , getBaseContext() and "this"

Write getApplicationContext().getContentResolver()
Hope this will work.

Ok it seems I fixed it myself by declaring Context on the beggining of the class.
public class NoteProvider extends ContentProvider {
Context context;
then initializing it in onCreate()
#Override
public boolean onCreate() {
mSQLiteOpenHelper = new NoteDbHelper(getContext());
context = getContext();
return true;
}
I think that made sure that I always have Context when I use context.getContentResolver().notifyChange(uri, null); or retCursor.setNotificationUri(context.getContentResolver(), uri); in insert/update/delete/query method- retCursor being returned cursor by mentioned methods.
I have run the aplication on my phone and did not have issues yet if I will there will probably be an edit for this post.
EDIT:
It does not make a difference after all - explanationin answer by #Mate, thank you for that I think I get it now :]

According to ContentProvider getContext() docs:
Retrieves the Context this provider is running in. Only available once onCreate() has been called -- this will return null in the constructor.
So the getContext() method does not return null in insert(), update() or delete(), because onCreate() will be called before these calls.
So it's OK to disable that warning for that line if you use it in such case...
//noinspection ConstantConditions
getContext().getContentResolver().notifyChange(uri, null);

Whenever you try to use a member or a method of an object, you can have a runtime exception if the object, whose member/method you try to use is null. Let's suppose you want to use a member/method of an object, obj. If you use it like this:
if (obj != null) {
//use members/methods of obj
}
then you prevented the problem. However, you might want to handle it as an exception, like this:
try {
//use members/methods of obj
} catch (NullPointerException npe) {
//handle the NullPointerException
}

Related

Toast in Android fragments showing null pointer expn

I am getting errors on few devices where I am trying to display a toast inside fragments. this toast is usually on retrofit response failure. toast code is simple. Please suggest, could not find any reason searching here and there.
Toast.makeText(getActivity(), "Connection Failure", Toast.LENGTH_LONG).show();
and my ST logs are below.
Fatal Exception: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference
at android.widget.Toast.(Toast.java:103)
at android.widget.Toast.makeText(Toast.java:256)
According to the code & javadoc for Fragment.getActivity() you can get null returned:
/**
* Return the {#link FragmentActivity} this fragment is currently associated with.
* May return {#code null} if the fragment is associated with a {#link Context}
* instead.
*
* #see #requireActivity()
*/
#Nullable
final public FragmentActivity getActivity() {
return mHost == null ? null : (FragmentActivity) mHost.getActivity();
}
Particularly this could happen when your Fragment is not attached to an activity (as pointed out here and here).
Similarly, getContext() can also return null.
There's a good discussion on when these can be null on this possibly related post:
Why getContext() in fragment sometimes returns null?
The simple solution has been provided already - put in a null check before displaying the Toast.
But the underlying problem is one of architecture - your code is coupling API activity to your UI, and assuming certain things about your UI state i.e. you are assuming that when the API call returns, your screen is still visible to the user.
A better solution would be to decouple the Retrofit call from the UI - put the API calls in a separate class that does not depend on the UI state.
Use an event or pub-sub framework to communicate from this API wrapper class back to any UI components that need to know when an API call returns.
EventBus or RxJava would be 2 common solutions for this (LocalBroadcastManager would be a less common approach).
This will allow any code to call into your API, and to subscribe to be notified when the API returns.
It also allows you to save your API responses in (for example) a local database, in which case you could just rely on the LiveData pattern to update any UI that needs to be.
Here's a Medium article giving a brief description of how to use the Android Architecture Components in this manner using the Repository pattern.
Given that some projects cannot be redesigned immediately, there may be need for workarounds.
The above mentioned null check workaround is useful in that the app will no longer crash. Unfortunately it does mean that the user will not be alerted to the failed API call.
One alternative is to create your own Application subclass (many projects will already have done this in order to initialise common libraries) and provide a method for static access to this application Context. (A similar suggestion has subsequently been made by Kushal.)
You could then choose to display the Toast using the application Context instead of the one from the fragment. You may lose any specific styling that would have been gained from the more specific context, but the advantage would be that your user still gets to see the Toast message.
Exposing your Application as a singleton has been described very nicely on this post:
Application singleton use in Android
Sometimes getActivity() or getContext() may produce a null pointer exception when the fragment is not associated with an Activity. So use the onAttach method
public class yourFragment extends Fragment {
Context context
#Override
public void onAttach(Context context) {
this.context = context;
super.onAttach(context);
}
}
Maybe getActivity() called when fragment detached. Try it.
if (isAdded()) {
Toast.makeText(getActivity(), "something", Toast.LENGTH_SHORT).show();
}
Your activity context is null in this line :
Toast.makeText(getActivity(), "Connection Failure", Toast.LENGTH_LONG).show();// getActivity() is null
To avoid crash use this :
if(getActivity() != null)
Toast.makeText(getActivity(), "Connection Failure", Toast.LENGTH_LONG).show();
Change your getActivity() to getContext(). try the given code below:
Toast.makeText(getContext(), "Connection Failure", Toast.LENGTH_LONG).show();
if (isAdded()) {
Toast.makeText(getActivity(), "something", Toast.LENGTH_SHORT).show();
}
or try this
if(getActivity() != null)
Toast.makeText(getActivity(), "Connection Failure", Toast.LENGTH_LONG).show();
Both will work fine in my case because in some case getActivity() called when fragment detached.
So we have to take care of that as well.

Instance method not called when declaring a Class-type instance variable and call an instance method in Esper

I'm writing an application that has an instance of a class that contains the esper engine. There are a number of instance variables that I would like to read and set using instance method calls from the EPL in the engine. I don't get any compilation errors and the code runs. But the instance method is not called.
epl statements:
module myModule;
create variable com.tp.main.MyClass myClass;
select myProperty from MyEvent unidirectional, method:myClass.getMyProperty() as myProperty;
A hint could be that if I don't use the method: key word in front of the method call I get an error that myClass.getMyProperty class could not be found. The documentation sometimes uses the method: key word and sometimes not in the examples for calling instance methods from Class-type variables.
I have also tried using the addVariable method in the API with the same results.
code for the method.
public Result getMyProperty() {
Result result = new Result();
result.setResult("propertyValue");
logger.info("This method was called");
return result;
}
The class Result is a POJO with getter and setter for a string.
public class Result {
private String result;
public String getResult() {
return result;
}
public void setResult(String str) {
result = str;
}
}
What am I missing?
You could look at a regression test class. The specific one you may want to look at is ExecFromClauseMethodVariable. Maybe your code does not assign a value to the variable?
Github:
https://github.com/espertechinc/esper/blob/3e396d77308532b202ee452100eaaf9e7a044906/esper-regression/src/test/java/com/espertech/esper/regression/epl/fromclausemethod/ExecFromClauseMethodVariable.java
Problem solved and I thought it might be useful to share the solution. Credit to user650839 who pointed me in the right direction. Here is what ended up fixing the problem.
I reverted back to declaring the variable in the runtime configuration API. I found that I must register the variable class, initialize it with the instance object (this) and finally import the class. Here is the snippet of code that does this configuration in the runtime configuration API.
Configuration configuration = new Configuration();
configuration.addVariable("myClass", com.tp.main.MyClass.class, this);
configuration.addImport(com.tp.main.MyClass.class);
epService = EPServiceProviderManager.getProvider(trade.getTradeName(), configuration);
It seems there is a limitation when declaring the Class variable in the EPL. You cannot initialize it with the instance object you want to use. In the runtime configuration API I was able to initialize it with "this" instance of the object which contains all of the instance variables I want to access from the EPL.
The EPL statement did not change. However, it does seem that you must use the key word method: in front of the method call or you get an error "cannot find class..."

How to throw compile time exception, if certain value is not set.

I have created an Android library, there is a method setContext()in it. Client need to pass context other wise app will crash at runtime. I need to throw an error on compile time, if user does not set context. I can't pass it throw constructor as its a singleton class.
Client
SampleLibrary sl= SampleLibrary.getInstance();
sl.setContext(this);
Class
public void setContext(Context context){
this.context= context;
}
Kindly guide me How to throw compile time exception, if certain value is not set or null.
doing this
sl.setContext(this);
is giving the option to developers to dont set the context, or forget to set it...
but if you define the class as
public SampleLibrary(Context ctx) then they are done! there is no other chance for them to create an object of SampleLibrary without giving a context
Avoid setting Context in a singleton. It could be null, or worth, create a memory leak.
You should pass the Context to the class constructor when you need it
If you want to throw an Exception at Runtime :
private setField(String value) throws IllegalStateException {
if (TextUtils.isEmpty(value) {
throw new IllegalStateException("Missing values");
// set your value here
}
public void setContext(Context context){
should be
public synchronized void setContext(Context context){
And of course it assumes that a single client uses the class.
Otherwise you could overwrite the singleton state between thread calls and it seems rather inappropriate that one thread works with the context set by another tread (in a race condition case).
Client need to pass context other wise app will crash at runtime. I
need to throw an error on compile time, if user does not set context.
A compiler is not designed to check the functional validation of the code.
It checks you respect the language rules and it is already very fine.
What you need is a runtime exeption that should be thrown if the user tries to manipulate the class while the context is not set.
To achieve it, you could do a check as first task in all public methods where the context is required.
Of course, you could create a private method and reuse it in each one of these places.
If the check fails, you throw a RuntimeException with the appropriate message.
If you want to really avoid to do these checks at many places, you can still use AOP.
try {
//your statement here
}
catch (RuntimeException ex)
{
//do something with the runtime exception
}

How to use Strings from strings.xml in another class

I'm currently writing an App, it gets JSON from a website, and then lists the contents in a listview. Now since the API itself only returns names like this: "twisted_castle" instead of "Twisted Castle", I created a new class to substitute the generic names to the right names, which I previously added to the strings.xml.
Now I can get Strings via String test = getString(R.string.key) in the MainActivity, but since I created a new class for the Substitute to happen, I somehow can't use getString somehow.
I already discovered that I'll need to get/use the context of MainActivity somehow, but really any solution I found didn't work, and also I'm a bit irritated on how the whole context thing works.
Anyone can help me with this and maybe has a good explanation on how contexts work?
You can use Context as:
mcontext.getString(R.string.something);
all you have to do is init context in the class some where like:
static Context mcontext;
public void setmContext(Context context){
this.mcontext=context;
}
and call setmContext(this) from your activity or where ever you have context attribute

null pointer exception on shared preferences

I've a method in my activity , How do I call that method from another class (Not from activity) , since I need to pass arguments to that class . Am getting nullPointerException if I create an object for my activity , please anyone help me
Dont put your data in Activity class . Generally from activy to activity Bundle params is used to pass data . BUt if you tell me your exact problem then may be taht we can find any solution.
Well not sure if i understood correctly but,
Can't you pass around a reference from the Activity to the "other" class method? Like :
class YourClass {
//bla bla bla
public void yourMethod(Activity activity)
{
if(null != activity)
activity.method();
else
//something
}
}
cheers

Categories