I have a very simple question:
Is or is it not possible to inflate a view (not add it to layout) in a background thread (ex: in the doInBackground of an AsyncTask)?
I know that it is possible, because I have implemented most Activities in my application this way and never had a problem, until I had this problem on a Galaxy S: Android: android.view.InflateException: Binary XML file line #13: Error inflating class <unknown> in SAMSUNG Galaxy S
I've been told that I should not inflate Views in background threads, but what are the specific reasons and why does my aproach work in most devices but not in Galaxy S?
The LayoutInflater does not make any assumptions about what thread it runs on. And nothing is mentioned about this in its documentation. Also its code seams to be thread-agnostic.
On the other hand, Views that are created by LayoutInflater might instantiate Handlers in their constructors. Well, they probably shouldn't do that, but there is no requirement for them to not create/use Handlers in their constructors.
My guess is that Samsung Galaxy S had some modifications in its EditText that somehow triggers creation of Handler (according to crash log from your other question instance of GestureDetector was instantiated which in turn created new Handler). While default implementation doesn't do this.
Overall, I'd say that because there is no explicit requirement for Views to not use Handlers and Loopers in their constructors you can't assume inflating Views from non-UI thread is safe.
You can actually create HandlerThread and try inflating Views inside it. But I'd say this is very risky, as in Samsung Galaxy S example the view assumes that this thread will be alive during View lifetime and will process all messages using its Looper. Which might result in crash later on.
With latest support lib you can use android.support.v4.view.AsyncLayoutInflater to inflate views asynchronously. Be careful though that it can fallback to inflating on UI thread if specific requirements are not met:
For a layout to be inflated asynchronously it needs to have a parent whose generateLayoutParams(AttributeSet) is thread-safe and all the Views being constructed as part of inflation must not create any Handlers or otherwise call myLooper(). If the layout that is trying to be inflated cannot be constructed asynchronously for whatever reason, AsyncLayoutInflater will automatically fall back to inflating on the UI thread.
Is or is it not possible to inflate a view (not add it to layout) in a background thread (ex: in the doInBackground of an AsyncTask)?
Possible, yes. Recommended? No. As mentioned in the documentation:
Thus, there are simply two rules to Android's single thread model:
Do not block the UI thread
Do not access the Android UI toolkit from outside the UI thread
via: Processes and Threads
Update [02/06/19]:
Apparently, the support library has a tool to do this:
AsyncLayoutInflater (Jetpack version). It was introduced in version 24, around 2016 (2 years after my answer)
But, as mentioned on other answers, be careful with this tool as it can very easily backfire.
Related
I know how to use the View.isInEditMode method.
What I don't fully understand is when should I use it. That is, what should I prevent from running in EditMode.
There are the obvious cases, where the custom view does all kind of crazy things like DB access, networking, threads etc. where it is clear you should avoid them while in EditMode.
I created a several custom views that don't do anything of the above. They only use the regular drawing API, or load resources such as drawables.
When running on device they look exactly as expected, but inside the layout designer they either don't look as they should or even just fail to render due to some mysterious exception (Usually NullPointerException).
So, are there any limitations in EditMode on these APIs?
Custom views should work just fine as long as they only call parts of the view framework, not any application code. That's a good separation to have for views anyway: they should contain view state, not app logic.
Typically you only have to use View#isInEditMode if your custom view is trying to access classes from its constructor (or measure or draw methods) where those calls for example try to access application framework code like say the FragmentManager. In that case you skip those calls with View#isInEditMode.
It's hard to say more about what the problem you're seeing is without knowing more. In particular, what exactly is the NullPointerException you're seeing (full stack trace).
It could also be a layoutlib bug. Try switching the render version (in the render toolbar) to a different version.
I am using setContentView(R.layout.main) to switch the views in the same activity. I am calling some asynchronous task and populating the data on the main layout file after that I am changing the view by calling setContentView(R.layout.main) method.
I came to know that we should not use setContentView method multiple times for same activity. Though it is working fine for me.
Can anyone explain why we should not use setContentView method multiple times for the same activity to change the views?
Will it create any memory related exceptions? Could someone please clarify?
I think switching Views is not a good idea, because android platform already have strong framework to handle the transition in between the views and maintaining the state of each view associated with the Activity its always better to stick with the existing framework instead of thinking of some complex implementation that you have to go through to do all these things. If you do not need any of these things to taken care in your application and if only if you have only two or three screen in your entire application you can try switching the views. That even based on how your views are structured if you have complex logic and lot of data needed to create these views this wont be a good way of doing it.One more thing if you are adding more views say functionality to your application the load that need to be handled by the Activity will go high. In this case you will be declaring and initializing all views inside that particular Activity so maintaining all these views instances is heavy. If you want to know more about the Activty and Task kindly refer this link
Well every time you call setContentView() you'll have to find all the layouts again besides that I think you "can" do it. But as discussed here this is ill adviced as it clearly goes against the android guidelines. Also Commonsware have some very important points here one of the most important being that you will be prone to leak memory as you forget to clean up stuff from your views etc. which Android normally would handle for you.
In short you should follow Android guidelines and use Fragments or start a new Activity.
According to the developer docs setContentView(int layoutResID) is used to
Set the activity content from a layout resource. The resource will be inflated, adding all top-level views to the activity.
In best practice this method is used to Inflate your Activity layout on start up. This does not mean that it will cause issues in the future if you keep using this method. To quote a answer in this question
The setContentView on your Activity actually calls the setContentView on the Window used by the activity, which itself does a lot more than just inflating the layout.
I suggest that you find a alternative way to switch layouts like using a ViewPager with Fragments or some other Tabbing approach but in the end it all comes down to what you want to do.
This question might also give you what you're looking for.
I m new in android.
i have a little bit confusion in SurfaceView and View......
According to my knowledge..
Views are all drawn on the same GUI thread which is also used for all user interaction.
I want to knw is it possible to create separate thread for the handling
Depends on what you define in handling.
If in handling you mean doing calcualtions, downloads etc. then yes.
If by handling you mean splitting control and view up, then no.
If your handling means that handling GUI things in other than GUI thread then Its not possible as Views are coupled with GUI thread or Android Component Activity. But non GUI threads alive even when your activity is finished , and It may leak the references to views. So it has been avided in al most all Programming models. Suppose if you are downloading the some values in Non GUI thread and then update your GUI views and in bwteen your screen orientation takes place and Your activity and its views are recreated but Non GUI thread is till now keeping the reference to old views . This can create old views to not to be collected by Garbage Collector and leak memory .
In my app, I've got 3 tabs. On clicking on each individual tab, some tab specific task happens. Now I am supposed to test the scenario of changing tabs from an android test project. In order to do that, I've called getTabHost.setCurrentTab(int tabIndex) method. But an error has been thrown saying
android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
The exception is quite self explanatory: "Only the original thread that created a view hierarchy can touch its views." In other words, you're trying to change the current tab from a different thread than the one that created it. More specifically, you have to do this action on the widget from the GUI thread - the thread that created the view hierarchy.
So you either have to move your setCurrentTab(int tabIndex) call to the GUI thread, or use a message mechanism. The latter is usually done using a Handler. Plenty of good examples and code snippets 'out there' that can show you how to go about this.
I'm developing an Android 2.2 application.
I have an event listener on an activity, and I want to set visible a TextView when I receive an event. But there is an error:
I only can set it visible from UI thread.
In C# and Windows Mobile there is a BeginInvoke. Is there something similar in Android?
Thanks.
You can use Activity#runOnUiThread or an AsyncTask as the two easiest ways to duplicate the BeginInvoke functionality; with runOnUiThread being the one most similar.
For more complicated or performance orientated needs (i.e., you do not want to keep creating a large number of Runnable objects) you can use a Handler. However, I do not recommend it as your first choice.