I am writing an android app, in which I have 1 button and 1 progress bar as UI elements.
The main aim of this app is when user presses this button, it has to create a database which contains all phone book contacts in customized format, means I am reading Contacts database and manipulating for my requirement.
So I am using SQLiteOpenHelper for database operations. I written a method downloadPhonebook() to perform all required operations. I written app such that when user presses button I am making progress bar visible and calling this method.
In this case, UI was hanged after clicking button and showing a dialog with Force Close and Wait buttons, after 15 seconds.
To avoid this I tried following mechanisms.
-> Broadcast Button click message and call method downloadPhonebook(). Here no use, same problem occurred.
-> Used a Thread and AsyncTask to call this method, here I got Runtime exceptions like Couldn't create Handler inside a Thread, Looper.prepare not called. I tried calling Looper.prepare() and Looper.loop() even exceptions occurred.
-> I tried with Android Service and Broadcast intent, again same problem UI hanged.
If anybody faced this problem or knows the solution or knows how to use Looper.prepare and Looper.loop please reply me. Thanks.
the workflow should be something like this: create a handler in your main class, add a handler in your sql helper class, pass the handler from the main class to the sql helper class when you create it. Run the download on separate thread from your main class, when download is ready, call yourHandler.sendEmptyMessage(0). You should override the Handler.handleMessage (I'm not sure about the exact name of the method) in your main class. You can also send messages to update the progress, read about Andoid Handler for more information
Related
I finished reading the Cursors and AsyncTasks chapter in Head First Android Development, and I'm still not sure when to use AsyncTask and when not to when performing database operations.
Suppose I'm at an activity which, when it ends, writes to sqlite database and sends the user back to the main activity (using finish()), which displays a list of data that is fetched from the database.
The list of data obviously has to update instantly, just as the user enters back to MainActivity. Does this mean I shouldn't use AsyncTask in this situation? What other choices do I have here? I don't want to let the user see the changed list of data after MainActivity is already visible.
A simpler scenario: The user clicks a button that should display database information in a TextView. Should this be done in a separate thread? I'm not sure, because the TextView must be updated immediately.
The best practice for read & write data in the database is: do it in a separate thread. Because it can take a lot of time, if the amount of data is fairly large or the query itself is too complicated, do it in the main thread can cause ANR.
If you want to display data changes immediately, you can do it as following:
place a method in the ui activity to change ui according to the parameters
triggered update ui through invoke the method above in the async callback
as for your last example, u can update the content of the textview immediately in the onPostExecute method of AsyncTask class
if you are not using AsyncTask u can just update ui in other thread through one of the ways below:
Activity$runOnUiThread(Runnable runnable)
new Handler(Looper.MainLooper()).post(Runnable runnable) //create handler for main thread, and post runnable to execute in main thread
send message to message queue, then handle the message and update ui in the main thread's handler
Normally you should do database queries on a separate thread, but if you're sure the database is relatively small(light) you could perform it on the main thread. but its always best practice to do potential long running tasks on a different thread.
Ok first of all android is really confusing. The scenario is I have about two runnable classes which are created from a Login View and if logged in it will create another view which will have other data and even more activities can be created from there
Now I can pass the the Login view context when creating a thread for the runnable class and edit out UI elements in them like this:
((Activity)someContext).runOnUiThread(new Runnable(){
public void run()
{
TextView txtErr = (TextView) ((Activity)someContext).findViewById(R.id.errMsg);
txtErr.setText("Some message");
}
});
But the issue is there will be more activities that will be created and the runnable class is created at the time of logging in, and I can't keep passing contexts.
Is there a better way for accessing the UI elements of different activities from different threads?
P.S: the threads which will be accessing the UI elements doesn't extend Activity and are running in a separate thread.
EDIT
I think I need to make my question more clear... I am developing a client app for a messenger... The process goes this way... User clicks on login button which creates a thread in a separate class named ClientThread for handling socket connection and keeping the connection alive till the user logs out or connection drops. The ClientThread class loops till the socket is connected and whenever some data is received the data is passed to another thread in a class named ProcessDataThread which do the parsing of data and will update the UI accordingly.
Now in a response from server if the user is logged in I want to create an activity from that class and keep a context to that activity in ProcessDataThread as I will be updating UI on further responses from server. And if login fails ProcessDataThread will display a message on the main activity saying login failed, now I was able to achieve the later by passing the context from the MainActivity to the two threads when clicked on Login like this:
global_constants.clientObject = new ClientThread(this);
global_constants.clientThread = new Thread(global_constants.clientObject);
global_constants.clientThread.start();
And then from ClientThread to ProcessDataThread
global_constants.updateConversationHandler.post(new ProcessDataThread(SharedBuff, cntxt));
But how will I create more activities from a non-activity class and do all update them or find a UI element etc...
Not sure if I understand you, but it sounds like you are trying to control the view of an activity from outside of the Activity. This sounds hacky to me. I'd let each Activity manage its own UI.
A good way of doing decoupled communication between objects is the observer pattern, aka an "event bus" or "event dispatcher" system. An example of how to do this on Android is here: http://www.therealjoshua.com/2012/03/event-dispatching-sending-messages/
Basically, the code that's generating the error should dispatch a message. The Activity can listen for this message, and then update its own UI as needed.
EDIT
Thanks for the clarification. I think the observer pattern can still help here. Basically, your data processing threads shouldn't know anything about the UI. Just have them post an event for the error, optionally with additional info on the error. If you want, your event dispatcher class could even make the actual event calls on the UI thread itself using a Runnable like you showed, so that the listener can always assume that they are being called on the UI thread, if this is important for your design. This way you don't have to pass the context to the thread at all (at least not for purposes of updating the UI) - let the worker thread just be responsible for the work, and the activity can be responsible for its own UI.
Another option you could use is an android Handler (see http://developer.android.com/reference/android/os/Handler.html)
In this case, the work is still done in another thread, but the Activity receives a handleMessage callback from the thread at the appropriate time. I haven't used this myself but from the documentation it looks like it can get the job done for what you need.
In either case IMO, the responsibility for updating the UI should lie with the Activity, not the worker thread.
I am a cub in android development but i am facing difficult problem now.Please try to help me.
In my app i have used onRetainNonConfigChange() to hold the object and used after activity created.
I know about handling this problem with AsynchTask thread with ProgressDialog but The same problem i can't able to handle with normal Thread and Hanlder.
I tried all the ways like make the Thread class as static and pass the parameters through on Handler class update the UI but...no use....
"How to handle screen orientation change with Normal Thread handler in android"
I think you should use AsyncTask still. Because it says in the SDK:
if your retained state is an AsyncTask you are guaranteed that its call back functions (like onPostExecute(Result)) will not be called from the call here until you execute the next instance's onCreate(Bundle).
I have an Activity that retrieves information from a remote server and displays it in a TableLayout.
The function that retrieves the information from the server has its own timeout, and exception is thrown when the timeout gets exceeded.
Now, when the activity is loaded, I want the function to be fired, and a progressDialog to be shown while the function works, and to be hided if the function is done working, or if a timeout exception was thrown.
The problem: I've put the code that do all the functionality described above in the onCreate() function. Nothing is shown on the emulator screen, since the onCreate() function hasn't finished running...
I've also tried to put the code in the onStart() function... same unwanted results...
I'm trying to avoid using of threads, because the functionality needs many variables that the thread will not has access to them...
How can i implement the wanted behavior??
Thanks.
Use AsyncTask with ProgressDialog bounded:
http://it-projects.spb.ru/?p=150&lang=en
Create a class implementing Runnable and put all your load logic in there. Call a function in the activity when finished (lets say onFinished(params...))
Create a UI Handler and get the handler to update UI in onFinished(params...)
Create a thread in onCreate and start it there to call your Runnable.
I have a comment activity that loads a Thread and sends some data to a server; the activity is immediately finished once the submit button is pressed.
The user is then free to do other things in my application.
When the server responds an AlertDialog is shown.
The problem is that since the initial context has been destroyed, my application crashes.
I tried getApplicationContext() but still get an exception.
Put your network stuff in a Service, then show a status bar notification instead of a dialog.
Take a look at AsyncTask
From JavaDocs:
AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.