Android findViewById in service - android

I am doing something like when a service get started, a custom toast notification shows up.
The custom toast view is defined in a xml file, the problem is that findViewById is not available in Service class.
Since it's a bad idea to start an activity in a service. So, how can i solve this problem ?

check this post
http://www.cloud208.com/blogica/Android+Custom+Toast+from+a+Service
According to that post, you can use an inflater with null as the second argument:
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.toast_layout, null);

Related

Fragment getLayoutInflater() vs. LayoutInflater.from(getContext())

Can anyone explain what's the difference between A and B in the following code snippet?
It's from a DialogFragment.
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
// A) this works
binding = DialogFragmentPeriodPickerBinding.inflate(LayoutInflater.from(context))
// B) this doesn't work: no compiler error, but dialog won't show
binding = DialogFragmentPeriodPickerBinding.inflate(layoutInflater)
[..] // binding.root is later on passed to setView(binding.root) of MaterialAlertDialogBuilder
}
Assuming you're using Fragment 1.2.3 (or Fragment 1.3.0-alpha02, which contains the same fix for a StackoverflowError when using layoutInflater in onCreateDialog()), you should always use layoutInflater. The fragment's layoutInflater is the only one that can correctly inflate <fragment> tags or its replacement, FragmentContainerView and connect those child fragments to your DialogFragment correctly.
However, if you're not using child fragments in your XML, you shouldn't see any difference between the two.
there is not much difference between layoutInflater and LayoutInflater.from(getContext()) in fact that two are pretty same thing if you look at the source code. problem with your code is that when you call layoutInflater in onCreateDialog its not set yet so our good friend android is trying to set now but it fails. because under the hood it calls onCreateDialog(SavedInstance) yes the function where you mentioned layoutInflater in order to get context from the dialog. so there we have infinite loop which will most likely lead us to crash.

How to fix "Method findViewById must be called from the UI thread, currently inferred thread is worker thread less"

I am working on layout inflater for designing multiple JSON array insted of using nested listview,How Can i set inflater for multiple array response from json?
I have used layout inflater method
Layout inflater =(LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View view = inflater.inflate(R.layout.activity_text_room, null);
TextView homeId=(TextView)view.findViewById(R.id.homeId);
I expect text view should be create but i got error like Only the original thread that created a view hierarchy can touch its views
In Android views cannot be changed in any other thread than the main UI thread. Depending on your code you might want to:
use runOnUIThread method of your Activity
Use AsyncTask class, its onPostExecute method is run in the UI thread.

Does inflater require Activity's context?

I sometimes inject link to LayoutInflater by Dagger, and produce it in module from Application context like this: LayoutInflater.from(application);. It reduces lines of code.
But colleges tell me that it is wrong way, and it has to be given from Activity context by LayoutInflater.from(MainActivity.this);
Is it true? Does behaviour of layout inflater depend on type of context?
Yes it is true. There's a big difference considering styles.
The LayoutInflater creates the views by calling their constructors. There it passes the context you passed to it. So if you use the application context instead of an activity context you might lack some information.
It's the same issue like using application context for creating views directly. Activities may define different styles and their contexts wrap these information.
Taking into consideration how you could get it, there's not a big difference. Internally LayoutInflater.cloneInContext(Context) is called to apply different context configurations.
Create a copy of the existing LayoutInflater object, with the copy pointing to a different Context than the original. This is used by ContextThemeWrapper to create a new LayoutInflater to go along with the new Context theme.
With the application context you don't get this.
If I understand things correctly, in case of using application context for creating LayoutInflater you have a chance to loose your Theme settings. See here for more details.
UPDATED
From source code of layout inflater:
Object[] args = mConstructorArgs;
args[1] = attrs;
constructor.setAccessible(true);
final View view = constructor.newInstance(args);
if (view instanceof ViewStub) {
// Use the same context when inflating ViewStub later.
final ViewStub viewStub = (ViewStub) view;
viewStub.setLayoutInflater(cloneInContext((Context) args[0]));
}
return view;
As you can see, your context (in your case application context) passes in constructions of View. It means that scope of your view will be application, not activity.
If we Application context means, the inflater instance exist throughout the application until the app is killed. In other case, if we use activity context the inflater instance will be removed once activity is destroyed.
you can use getApplicationContext() when you know you need a Context for something that may live longer than any other likely Context you have at your disposal like services .
So It is best practice to use activity context when you dont need your object that will hold for long time or to global scale.
Hope it will help.

What is the difference between the inflaters

What is the difference between doing
LayoutInflater inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
and inflater = LayoutInflater.from(activity);
What is the difference between the inflaters
Difference is that in second example (via static method), you don't need to cast Object to LayoutInflater because it returns directly LayoutInflater instance.
First case returns generally Object that you have to explicitly cast to LayoutInflater. But result of both methods is new instance of LayoutInflater
Is up to you which method you'll pick up. I usually use LayoutInflater.from(); method and never have problems. I don't need to cast from Object and it'll make a trick.
As #CommonsWare mentioned, you can also call
getLayoutInflater()
If you are in Activity class (it's method of Activity). But when you are not in Activity you need to have Context variable and then you can call (for example from ListAdapter):
((Activity) context).getLayoutInflater();
But i think when you are not in Activity it's much easier and efficient to call LayoutInflater.from(); instead of approaches above.

context vs views

can anyone explain the difference between context and views and when do we go for context or view ? In most of the program I find either context or view being passed to certain methods , what is actual need of passing context or view to methods?
This is a strange question. View describes one element of your ui. It can have onClickListeners, properties and so on. But every view is created in some context, usually Activity's context.
Context as itself is something like environment your code is executed in. It has access to ui(if it is an activity), it can contain some global data(application context), and has access to the resources(all of the contexts). Also, context allows you to perform common android operations like broadcasting intents, start activities and services.
So, views should be passed when you want to do something with a particular view.
Context is passed when you need access to resources, global data or ui context, or launch other android components.
We need to understand how View is constructed and what is Context.
View has three constructors, all of which use Context as an argument.
In Activity, if view is inflated programmatically as against in XML, view is inflated a View is by using LayoutInflater.
LayoutInflater takes Context as an argument and internally saves it in a class level field.
LayoutInfater layoutinflater = LayoutInflater.from(this);
where "this" is the Activity instance.
When inflater inflates view i.e. :
inflater.inflate(R.id.some_view, parent, null),
it is internally passing the saved context field to the constructor of View.
View always takes a Context as an argument and this is obvious because views live in some Context which is the Activity.
To answer your question, when context is needed to be passed to a method which itself is in Activity, you can write "this". If method is not in Activity, and you need to pass Context, then remember that View which has taken Context as a parameter, saves the object reference in a class level field. We can get this object reference by writing view.getContext().

Categories

Resources