Side effects of calling Activity.setContentView() twice in a row - android

In my app I needed to call findViewbyId() from both onCreate() and from WebChromeClient.onCompletion(). To avoid findViewbyId() returning null I resorted to calling Activity.setContentView(int viewResID) before calling findViewbyId().
It works, but now I am wondering whether I may have created a "time-bomb" in my code down the road.
Are there any caveats that I need to keep in mind when doing something like this?

There is no problem in doing so. You have to reinitialize references (every findViewById needs to be called again) and it might be troublesome if you do it A LOT of times, but it is not a time bomb at all.

Related

Why Is OnCreate Preferred To Do All The Main App Tasks?

Why Is onCreate() Preferred To Do All The Main App Tasks? Why not onResume() or onStart()? Why only onCreate()? I tried to do the main tasks like binding findViewById() setting text to text views and a lot more. They all work fine. When why do we always are preferred to do that task in onCreate()?
OnCreate serves as the first entry point into your activity, so logically it makes sense to do as much of the initialization here as possible. Often times there are cases when things need to get configured with higher priority - crash reporting services, dependency injection etc. where this would get escalated to a custom application class.
according to the docs
protected void onCreate (Bundle savedInstanceState)
Called when the activity is starting. This is where most initialization should go: calling setContentView(int) to inflate the activity's UI, using findViewById(int) to programmatically interact with widgets in the UI...
so, I suppose it is fair to say that most initialization will get done inside of onCreate, which usually means that if you were to place this into a lifecycle method which could get executed repeatedly, that could be considered redundant as you'd be assigning the same values to variables repeatedly, unless that's something you actually want to do.
However, lazy initialization is also a concept to keep in mind, being able to initialize something inside of onCreate doesn't always mean that you should, it is often times better to delay initialization until you actually need the instance.
regarding
I tried to do the main tasks like binding findViewById() setting text to text views and a lot more. They all work fine.
they definitely would, findViewById can always be used and isn't limited to being inside of onCreate, in fact the result of findViewById doesn't even have to be assigned to a variable for you to be able to use it

What exactly happens when you fail to use unbind()?

I have an app where I use Butterknife, and recently I found a fragment where I had failed to call unbinder.unbind() in the fragment's onDestroyView(). I fixed the problem but it made me start thinking.
What kind of errors can this cause and why? I don't have a particular error right now but I would like to know what to watch out for in the future, and the website for the library doesn't specify the problems this could cause.
Imagine you have a retained fragment and you have initialized a view using #BindView.
An orientation change happens, which results in destroying activity instance, but not this fragment, because this fragment is a retained fragment, which means, that the field that you have initialized is still there (not null) and is holding a strong reference to the view of the previous activity, which results in leaking of the activity.
Although this might take for some small amount of time (because eventually you are going to perform another ButterKnife.bind() in onViewCreated(), right? But who knows, maybe you won't), still it is better to release resources as soon as you do not need them and let the GC do its job.
I've also thought about this question some time ago and other than this I couldn't come up to another scenario where unbind() would be strongly necessary.

Invalidate is failing to call onDraw when returning to an activity that has a custom view

I have inherited some code hence I don't have true freedom to change it. :(
I have a main activity, from which other activities (I will refer to these as sub activities from now on) are called. Whenever one of these completes, it calls finish and returns data to the main activity.
Each activity (including the main one) has a bar on the top that displays a custom view. The custom view contains a canvas which has a drawing that is dependant upon the state of the network.. i.e. wifi/mobile etc...
Since that 'state' data never changes, it's held within a singleton and the view gets data from the singleton to define what it draws. That is working with no issues, i.e. the data is always as I expect it.
When I first launch the MainActivity, as the network changes, the data changes and each call to 'invalidate' the view receives a system call to 'onDraw' as I would expect.
In each of the sub activities the same is again true.
Upon finishing a sub activity and returning to the mainActivity, calls to invalidate no longer cause a call to onDraw to occur.
I have looked at this for quite a while now and just cannot figure out what is going wrong.
In my constructor I have:
setWillNotDraw(false);
Whenever the data changes the following methods are called:
invalidate();
requestLayout();
Now, there's one more thing... upon returning to the activity at that immediate point, I refresh and this DOES draw correctly, i.e. invalidate does trigger an onDraw call... any subsequent network changes (which are propogated) fail to result in the onDraw call.
I'm wondering if this is to do with the view somehow being detached. I can see that 'onDetachedFromWindow' is called, however the trigger for this is the destruction of the subactivity, hence I don't see why that should affect the MainActivity but it's the only thing I can think of.
I'm hoping I've provided enough information for someone to help me...
Well, in the end my answer has very little to do with the question and I guess this is an example of how an issue can be solved by going back to absolute basics and checking for the obvious.
My activities all inherit from an abstract activity. Within that activity there is an instance of the view. The views in which I was having trouble were using that declaration as opposed to having their own instance, hence behaviour from one activity was then affecting another inadvertently.
So, if I'd been able to post up all the code, I'm sure someone else would have spotted this but, unfortunately I couldn't in this instance.
Still, whilst this posting doesn't provide a resolution that will help others, maybe it does say... step back and check the obvious first!

Activity fields referencing UI elements

It would be "cheaper" to store reference to layout element rather than findViewById every time you need it, but wouldn't it prevent garbage collection? My assumption is that in onStop state views get destroyed, at least onSaveInstanceState is called. So, reference to a UI element in activity or fragment prevents the element from being collected - right ?
Am I wrong or should I stick to findViewById or try weakreferences ?
Thanks.
My preferred way is to store the view reference in activity if it will be accessed multiple times.
Invoke findViewById everywhere makes code ugly i think.
I don't believe store the view reference will impact the gc, cause you can use Activity to access all ui element, their references are already held.
The answer is : It depends,
If you are going to be referencing the UI repeatedly, It would be cheaper to save the references. It not, then you can just use findViewById a couple of times. In most apps under normal conditions, Either way wouldn't make much noticeable difference to performance as these tasks are not very system intensive. So my final answer would be, Do whatever is most comfortable for you in your workflow since performance gains/losses are almost negligible (unless you do this a huge number of times of times).

Activity.findViewById returning null sporadically

From the crash logs that I am getting from the Android market, I can see
that some of my users are getting Force Closes caused by
NullPointerExceptions when my code tries to access views that are in my
application. In one example, my activity makes a call to findViewById()
in onCreate() after I call setContentView(). I get an NPE when I try to
access the view after the call to findViewById() (still in onCreate).
What has me really scratching my head is that this does not happen all
of the time (in fact most of the time the code acts as I would expect),
but enough to have me concerned.
I could add code to always check for null and avoid the NPE, but I
would like to understand what could be causing the sporadic behavior.
Does anyone know what could be causing this?
Rename that view may be you can find the view as expected.

Categories

Resources