Can Android have multiple listeners? - android

Say I have 5 buttons. For each button I want to be able to fire a listener.
Once the listener is fired I want fire an async task in my sdk, and then have the sdk return the status of the async task.
1) Do I write a separate listener/ button? I read somewhere I can have only one registered listener in android, if thats true how do I handle many listeners?
2) How do I return postExecute call result from SDK to the api level?

1) Do I write a separate listener/ button? I read somewhere I can have only one registered listener in android, if thats true how do I handle many listeners?
A View can only have one listener of each type, ie a Button cannot have two OnClickListeners. Don't confuse this with the fact that one listener can be attached to multiple Views, ie ButtonA and ButtonB can have the same OnClickListener
2) How do I return postExecute call result from SDK to the api level?
Your terminology isn't right, but you'll figure it out as you go. Typically onPostExecute() will call another method or work directly with a View:
#Override
protected void onPostExecute(String result) {
doSomething(result);
textView.setText(result);
}

Easiest is if you setup one listener in your activity, and then handle multiple buttons. You can do this with the OnKeyListener class. You then do a switch on which key was hit, setup cases for the buttons you wish to act on, and start your AsyncTask.
I'm not quite sure what you mean by "return postExecute". But if you look at AsyncTask you can see how to use the proper parameters to return a result into onPostExecute. When you instantiate your subclass of AsyncTask you can easily pass in the activity or context you wish to perform a call back on.

You can have multiple listeners and depending on what you want to do with them, you can have one for each button. As far as the postExecute(), it runs on the UI thread so you can show your result from there or do whatever you want with it. For more details, you will need to provide some of the code you have tried and explain exactly where you are having trouble. If you haven't already, go through the
Android Docs about getting started
This link describes AsynTask

Related

Android difference between callback and listener

So in my understanding listener is usually used to trigger some class when some thing happened on particular place. (for example when we click the button we want to do some action).
On the other hand I see some places where callbacks are used to execute/enqueue some code in different place. (retrofit uses this to enqueue API calls)
What is the main difference between these 2?
In short, they are the same.
Really?
Yes. But there are some "theoretical" (and in some cases practical differences).
Concepts
Listener is a word that in Android, it's commonly associated with a View ClickListener or similar. Where there are methods like addxxxListener(...) etc.
A Callback is often heard in the context of "for this particular event" I supply a "callback" and I will be called back when something happens.
In practice, they are often just instances of some interface passed along.
In my limited experience (only about 10 years of Java/Android -now Kotlin as well-), the term is used interchangeably.
I normally think of a callback when I am expecting something to "call me back" when something happens, and a listener as something where I listen to an event but as you can see by reading this... they could be the same. :)
It's often mentioned that one could have multiple listeners, but one callback (but there's nothing enforcing this and I have seen all use cases you can think of where either term is used) "You can add multiple callbacks" is not uncommon, even though if there are "multiple" then it "must be a listener". In fact, if you go as far as Android's View, the method is view.setOnClickListener { }
So it's a Listener, but you can only set ONE. So the above rule about 1 callback, N listeners is already broken since the early days of Android.
In some cases though, the convention is more tied to the method name, rather than the class' name:
setXXXyyy(...) allows you to set "one" and only one yyy listener/callback.
addXXXyyy(...) allows you to add one or more (though not always, so read the documentation) yyy listener/callback.
An add is often (...but not always) accompanied by a removeXXXyyy(...) implying that if you keep/have a reference to a callback/listener you could remove it (and no longer be listening or be called back).
In the case of set, it's often expected that if needed you call set...(null) and pass that null to "remove" the sole listener/callback. (Views do this for you, you don't need to call it, but you can).
Anyway, don't quote me on this, but I'd argue they are the same. This is also more complicated when you involve other languages/frameworks/tools, where there's an even blurrier line.
In many instances, you will see callback used, but the method contains the word "Listener", and vice-verse, so don't get too crazy about it.
If you can, where you can, however, don't use either, just use Coroutines :)
For a concrete example of how both are used as the same thing...
Look at the Android View.setOnClickListener method:
/**
* Register a callback to be invoked when this view is clicked. If this view is not
* clickable, it becomes clickable.
*
* #param l The callback that will run
*
* #see #setClickable(boolean)
*/
public void setOnClickListener(#Nullable OnClickListener l) {
Notice something strange?
The method is called setOnClickListener yet the Javadocs say: "a callback..."
They are the same! Two ways of naming an interface. In general, Listener is also a callback and VICE VERSA!
for a type of event you can have many listeners , but one callback !
A callback is a procedure where you pass as an argument to another procedure. The procedure receiving the parameter can call it, or share it so some other procedures in the system can call it.
A listener watches for an event to be fired. For example, KeyListener waits for KeyEvents, a MessageListener waits for messages to arrive on a queue, and so on.

Listening UI Events on MainThread(UI Thread) and what view that triggers the event

is there anyway to listen on UIevents such as button click on main/ui thread? without interacting directly on each UI's callbacks(e.g onClickListener) ?
I just want to listen to any thing it fires from ui events, I've been digging around but I only find something that posts message to the ui thread from another thread, what I want is just listen to UI thread when for example a button is clicked,
findViewById(R.id.button_1).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// some button click stuffs here
}
});
// this is where I want to listen from ui events (e.g click),
// and determine what type of view that triggered that event
// or how to get the actual view object that triggered it
I'm assuming that this could already be asked(It will be fine if this will be marked as duplicate, but please provide a related post if there is/are), every time I try to search for something like "listen to main thread", I cant find something like what exactly I need, Any help would be greatly appreciated, or any related links.
Edit: the current situation is, there is no way for me to interact with an existing code, so I'm trying to find a way to listen on those UI events without touching the actual codes(via separate module/library), I dont know if this is possible to achieve though
i think there is no direct way to do that, if you want to handle it outside, use the Handler

Several simultaneous AsyncTasks from different Activities - how to catch proper response?

I have several Activities and each of them has its own AsyncTask which sends requests to a server and catches its responses. These days if AsyncTask is in execution I have a ProgressDialog which blocks User from navigation to another Activities. I want to get rid of the ProgressDialog and substitute it with ProgressBar view so user can switch between Activities. My concern is about the following: what if AsyncTaskFirst started in ActivityFirst and user navigates to ActivitySecond where AsyncTaskSecond is starting also, couldn't it happen the response from the first request will take ground in ActivitySecond so I'll miss it in ActivityFirst? If it is impossible, that's fine. If it is - how to handle such a case? Thank you very much in advance.
If the AsyncTask begun execution in the first Activity then it's execution of the postExecute method should be expected to affect the first Activity and not the second unless you've explicitly set it up otherwise.
I assume your AsyncTask has some kind of reference to the Activity, so it can update the progress bar.
If this is so, then all you have to do is add a method in the AsyncTask:
public void setHandler(MyTaskHandler handler) {
this.handler = handler;
}
When you start a new activity, call this method and pass on the new activity.
Then when the AsyncTask calls the Activity's update progress method, it will use the current Activity regardless of where the task was started from.
BTW: It might be better to use fragments and not activities, if it's the same component only different parts of the display. Then you do not have this problem at all, because the activity remains the same. See these guides about fragments:
http://developer.android.com/training/basics/fragments/index.html
http://developer.android.com/guide/components/fragments.html

Display loading screen using AsyncTask with ListActivity

I've got an app that uses ListActivity to give users a list of actions. When they click one I use an Intent to launch a separate activity.
My problem is that the actions that the app performs take about 20 seconds to finish, and since I don't want the user to receive that nasty ANR dialog, I tried to use AsyncTask to present them with a loading screen in the mean time. I tried using setContentView(R.layout.loading); on onPreExecute(), but it throws a NullPointerException which as far as I have figured out is due to the fact that loading.xml is not "a ListView whose ID is android.R.id.list".
So what can I do now? How can I show that loading screen? Is there a way around this pretty annoying situation? Any help would be greatly appreciated. Thanks!
I am not sure exactly what your use case is; you have a list of items that are populated immediately, and upon selecting one an action is taken? The action that is taken is to launch another Activity which performs background processing?
Or does it take that long to populate the list of actions?
If the former, you can use an AsyncTask for the long-running activity instead of an Intent to launch another Activity: in the callback you get for the click on the item in question, you would create the AsyncTask, and in doInBackground you would perform the long-running activity, with onPostExecute refreshing or manipulating your list as necessary.
Another thing to consider is using a dialog box to show a loading screen, if the loading is required to happen before you launch a new Activity.
If you can further describe your use case, I can help you more.
It's not the loading screen you need to have on the AsyncTask, it's that 20-second Activity initialization. I would look for a way to do all the setup in a background thread in a Service while the user is free to merrily bop around in other Activities. I'd try hard to find a way not to just stall the user for 20 seconds. Maybe take them to the target Activity and show them data cached from their last visit until the new set is ready.
Fire up and display your loading dialogs in your onCreate() of the Activity being called, then call Dialog.dismiss() in your AsyncTask's onPostExecute().

Asynctask API call issue

I'm currently using an AsyncTask to make an API call and populate a list with data.
I have a Sub Menu whose items can call the AsyncTask to populate the data, problem is that if i click quickly i end up with merged results obviously cause the AsyncTask is running at the same time as each other.
What is the best way to handle a situation like this? Sorry if this is a amateur question.
I would use a ProgressDialog to show that content is being updated, and when the update is complete, dismiss() the dialog. While this is happening, you should make sure that you are not accepting touch input on your ListView. (this may happen by default when the ProgressDialog is in front, I am not remembering currently...)
Take a look at this link for an example.
You could configure only a single Asynch task to run at a time.
A boolean variable which is set to true as soon as the asynch task starts and set to false as soon as it finishes.
Next call could wait for this to be set to false. You could also rate limit what is the min time after which only making the API call makes sense.

Categories

Resources