Android: wait on user input from dialog? - android

I would like to implement a method that displays a dialog, waits until the dialog is dismissed, and then returns a result depending on the dialog contents. Is this possible?
public String getUserInput()
{
//do something to show dialog
String input = //get input from dialog
return input;
}
I am actually trying to implement an interface which has method "public String getUserInput()", where the returned String must be retrieved via dialog. This is easily done in java, seems impossible in android?
EDIT: Posting some sample code as requested in comment
getInput() must be called from a background thread (I call it from an AsynchTask). getInput() displays a dialog and calls wait. When the ok button is pressed on the dialog, the dialog sets the user input in a member variable and calls notify. When notify is called, getInput() continues and returns the member variable.
String m_Input;
public synchronized String getInput()
{
runOnUiThread(new Runnable()
{
#Override
public void run()
{
AlertDialog.Builder alert = new AlertDialog.Builder(context);
//customize alert dialog to allow desired input
alert.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton)
{
m_Input = alert.getCustomInput();
notify();
}
});
alert.show();
}
});
try
{
wait();
}
catch (InterruptedException e)
{
}
return m_Input;
}

Is this possible?
No. There is no blocking UI model in Android. Everything is asynchronous.
UPDATE
In response to some of your comments on the question itself, you cannot display a UI from a background thread. As I wrote in this answer, there is no blocking UI model in Android. Just put your code in the button handler for your dialog that you want to have executed when the dialog is accepted, such as in this sample project.

The right way to do this is an event driven program model, ie, "don't call us, we'll call you".
In simple console mode programming, your code tends to call blocking input functions, which don't return until you've gotten a value.
Many gui programming environments work differently - your code is not normally running, but instead it's called by the operating system / window manager when something of potential interest happens. You do something in response to this and promptly return - if you do not, you can't be notified of anything else since the OS has no way to contact you until you return. (In comparison to win32, it's as if the message loop is implemented by Android, and you only get to write the rest of the code that the message loop calls with events - if you don't return promptly, the message loop hangs)
As a result, you need to rethink your concept of program flow. Instead of writing out a to-do list as a simple series of statements, think about it as a sequence of actions which depend on each other and on input. Remember what action you are currently on in a state variable. When you get called with an event such as user input, see if that event means it's now possible to move on to the next step, and if so update your state variable before promptly returning to the OS in order to be able to receive the next event. If the event wasn't what you needed, then just return without updating your state.
If this model won't work for you, what you can do is write a background thread of program logic which runs like a console-mode application using blocking input. But your input functions will really just wait on a flag or something to be notified that input is available. Then on your UI thread where Android delivers events, you update the flag and promptly return. The background thread sees the flag has changed to indicate that data has been provided, and continues execution. (Something like an android terminal emulator takes this to an extreme, where the background component is actually another process - a console mode linux one, and it gets its input using potentially blocking I/O from pipes. The java component accepts android UI events and stuffs characters into the stdin pipe and pulls them out of the stdout pipe to display on the screen.)

Thanks for all the feedback, I was able to solve this using a background thread along with a wait() and notify(). I recognize this isn't the greatest idea for the given paradigm, but it was necessary to conform to a library that I am working with.

I had a hard time understanding all the solutions offered above so far so I found my own one.
I wrap the code thats supposed to be performed after the user input is OK'ed in a runnable, like so:
Runnable rOpenFile = new Runnable() {
#Override
public void run() {
.... code to perform
}
}
Then right below that I pass the name of the runnable function to the user dialog method.
userInput("Open File", rOpenFile);
The userInput method is based on the alertDialog builder like described above. When the user input is Ok'ed it starts the intended runnable.
private void userInput(String sTitle, final Runnable func) {
AlertDialog.Builder aBuilder = new AlertDialog.Builder(this);
aBuilder.setTitle(sTitle);
final EditText input = new EditText(this);
input.setInputType(InputType.TYPE_CLASS_TEXT);
aBuilder.setView(input);
bDialogDone = false;
aBuilder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
final String sText = input.getText().toString();
sEingabe = sText;
func.run();
}
});
aBuilder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
sEingabe = "";
}
});
aBuilder.show();
}

Something like this would do
/**
*
*/
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
/**
* #author
*/
public class TextEntryActivity extends Activity {
private EditText et;
/*
* (non-Javadoc)
* #see android.app.Activity#onCreate(android.os.Bundle)
*/
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_text_entry);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND,
WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
// title
try {
String s = getIntent().getExtras().getString("title");
if (s.length() > 0) {
this.setTitle(s);
}
} catch (Exception e) {
}
// value
try {
et = ((EditText) findViewById(R.id.txtValue));
et.setText(getIntent().getExtras().getString("value"));
} catch (Exception e) {
}
// button
((Button) findViewById(R.id.btnDone)).setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
executeDone();
}
});
}
/* (non-Javadoc)
* #see android.app.Activity#onBackPressed()
*/
#Override
public void onBackPressed() {
executeDone();
super.onBackPressed();
}
/**
*
*/
private void executeDone() {
Intent resultIntent = new Intent();
resultIntent.putExtra("value", TextEntryActivity.this.et.getText().toString());
setResult(Activity.RESULT_OK, resultIntent);
finish();
}
}
The launch is:
public void launchPreferedNameEdit() {
Intent foo = new Intent(this, TextEntryActivity.class);
foo.putExtra("value", objItem.getPreferedNickname());
this.startActivityForResult(foo, EDIT_PREFERED_NAME);
}
You get the result by using
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case EDIT_PREFERED_NAME:
try {
String value = data.getStringExtra("value");
if (value != null && value.length() > 0) {
}
} catch (Exception e) {
}
break;
default:
break;
}
}

CASE: My data was ready to be processes after a preference change listener event and I needed to add a String queried from user. It doesn't appear possible to pop an alert dialog while the options menu is open...so I had to wait. I threw the half complete object into the next activity in the workflow and set its onResume() to check if its placeholder was !null in which case I popped the dialog and finished up the object *"in the button handler of the dialog"*.
Since this is my first post I can't vote for the correct answer given above but want to save anyone else running into this the time and in-elegance of less correct solutions. The dialog is the place.

You can think in terms of a state machine where if you initially require first-time user input you can have a flag set to mark "user input needed" or whatever. Then upon processing an event you check that flag and if set you fire up a dialog as the only action for the event and unset the flag. Then from the dialog event handler after handling user input you can call the code normally intended for the case when a dialog is not needed.

For your reference, I just made a dialog.
It would show and wait then dismiss.
And I deploy Java wait and notify to make it, this function can be copied and run directly.
private final Object lock = new Lock();
private static final class Lock {}
private void showWaitDialog(final String message, final int time_to_wait) { //ms
if(this.isFinishing()) return;
final String TTAG = "[showWaitDialog]";
Log.d(TTAG, "dialog going to show");
final ProgressDialog waitProgress = ProgressDialog.show(this, "WARNING", message, true);
waitProgress.setCancelable(false);
waitProgress.setOnShowListener(new DialogInterface.OnShowListener() { //callback got the asynchronous
#Override
public void onShow(DialogInterface dialog) {
Log.d(TTAG, "dialog showed");
synchronized (lock) {
try {
Log.d(TTAG, "main thread going to wait");
lock.wait();
} catch (InterruptedException e) {
Log.e(TTAG, e.toString());
Log.e(TTAG, "main thread going ahead");
}
}
}
});
new Thread(new Runnable() {
#Override
public void run() {
synchronized (lock) {
try {
Thread.sleep(time_to_wait);
} catch (Exception e) {
Log.d(TTAG, e.toString());
}
lock.notifyAll();
Log.d(TTAG, "dialog notified");
waitProgress.dismiss();
}
}
}).start();
}

Related

How can I force a blocking redraw of a UI element?

I have a simple login page where the user enters a password, and that password is used to decrypt some data and create the main activity. The process of generating the key, calling the database and creating the main activity takes about 5 seconds so I want to show a progress wheel on the login screen immediately after the user clicks the login button.
Unfortunately since android handles UI refreshes in a non-blocking way the progress bar won't appear before the login function runs. I can't seem to find a way to force a blocking UI refresh for a view in Android. invalidate() and postInvalidate() both won't work since these simply notify Android that a redraw should happen at some point in the future.
Here is some sample code to explain what I'm trying to accomplish:
try {
progressBar.setVisibility(View.VISIBLE);
passwordEditText.setEnabled(false);
Key key = doLogin(passwordEditText.getText()); // Long operation
Intent intent = new Intent(getActivity(), MainActivity.class);
intent.putExtra("Key", key);
startActivity(intent);
getActivity().finish();
} catch (Exception e) {
passwordEditText.setError(getString(R.string.login_error));
Log.e("Login", e.getMessage());
} finally {
progressBar.setVisibility(View.INVISIBLE);
passwordEditText.setEnabled(true);
}
If it's not possible to override the default behaviour and force an immediate blocking redraw, then how best can I best implement a progress wheel while the doLogin() method runs?
I can't seem to find a way to force a blocking UI refresh for a view in Android
Correct. That is not how the Android view system works.
then how best can I best implement a progress wheel while the doLogin() method runs?
Have doLogin() be performed on a background thread. Update the UI on the main application thread when the background work finishes. Take into account that your UI may no longer exist (e.g., user pressed BACK) or may be replaced (e.g., user rotated the device or otherwise triggered a configuration change) while that background work is going on.
In modern Android app development, the three main approaches for doing this are to use a ViewModel and LiveData along with:
RxJava
Coroutines (for app development in Kotlin)
Your own background thread
Fixed the issue. Here's my solution. It may be a little overdone, but I tried to make it easily expandable so it can be applied to other similar scenarios.
AsyncTask for login:
static class LoginTask extends AsyncTask<String, Void, LoginTask.LoginTaskResultBundle> {
private TaskActions mActions;
LoginTask(#NonNull TaskActions actions) {
this.mActions = actions;
}
#Override
protected void onPreExecute() {
mActions.onPreAction();
}
#Override
protected LoginTaskResultBundle doInBackground(String... args) {
try {
Key key = doLogin();
return new LoginTaskResultBundle(LoginTaskResultBundle.SUCCEEDED, key);
} catch (Exception e) {
return new LoginTaskResultBundle(LoginTaskResultBundle.FAILED, e);
}
}
#Override
protected void onPostExecute(LoginTaskResultBundle result) {
if (result.getStatus() == LoginTaskResultBundle.SUCCEEDED)
mActions.onPostSuccess(result);
else
mActions.onPostFailure(result);
}
// Result Bundle
class LoginTaskResultBundle {
static final int FAILED = 0;
static final int SUCCEEDED = 1;
private int mStatus;
private Exception mException;
private Key mKey;
LoginTaskResultBundle(int status, Key key) {
mStatus = status;
mKey = key;
mException = null;
}
LoginTaskResultBundle(int status, Exception exception) {
mStatus = status;
mException = exception;
}
int getStatus() {
return mStatus;
}
Exception getException() {
return mException;
}
Key getKey() {
return mKey;
}
}
// Interface
interface TaskActions {
void onPreAction();
void onPostSuccess(LoginTaskResultBundle bundle);
void onPostFailure(LoginTaskResultBundle bundle);
}
}
Sample call to the LoginAsyncTask:
new LoginTask(
new LoginTask.TaskActions() {
#Override
public void onPreAction() {
showProgressBar();
}
#Override
public void onPostSuccess(LoginTask.LoginTaskResultBundle bundle) {
launchMainActivity();
}
#Override
public void onPostFailure(LoginTask.LoginTaskResultBundle bundle) {
hideProgressBar();
passwordEditText.setError(bundle.getException().getMessage());
Log.e("Login", bundle.getException().getMessage());
}
} )
.execute(passwordEditText.getText().toString());

Force show keyboard doesn't work unless you run in background thread

Here's the project showing what works and what doesn't. Code is also below. I've found many stackoverflow posts showing the clear solution for this, but for some reason that doesn't work for me unless I run it in a background thread.
I'm creating an AlertDialog and an EditText. My goal is to show the alert dialog, show keyboard, and have cursor in the edit text. For some reason, I cannot just RequestFocus and ShowSoftInput. It only works when I create a background thread, then make the call... Why is that? Am I doing something wrong?
Here's a screenshot of what the app looks like when I run the code in the background thread vs not...
Link to Xamarin Android project:
https://drive.google.com/open?id=0B5x7JEZ8aQihVnM4am8yRWlQYkU
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
// Get our button from the layout resource,
// and attach an event to it
Button button = FindViewById<Button>(Resource.Id.myButton);
button.Click += delegate { button.Text = string.Format("{0} clicks!", count++); };
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(this);
AlertDialog alertDialog = null;
TextView titleTV = new TextView(this);
titleTV.Text = "title";
titleTV.TextSize = 18f;
titleTV.SetTextColor(Android.Graphics.Color.Green);
titleTV.SetBackgroundColor(Android.Graphics.Color.White);
titleTV.SetPadding(0, 12, 0, 12);
titleTV.Gravity = GravityFlags.CenterHorizontal | GravityFlags.CenterVertical;
alertBuilder.SetCustomTitle(titleTV);
EditText editText = new EditText(this);
editText.SetHeight(600);
editText.Text = "super coooool dude";
editText.TextSize = 14f;
editText.SetPadding(18, 12, 18, 12);
editText.Gravity = GravityFlags.Left | GravityFlags.Top;
editText.ShowSoftInputOnFocus = true;
editText.RequestFocus();
alertBuilder.SetView(editText);
alertBuilder.SetPositiveButton("Done", (sender, e) => { });
alertBuilder.SetNegativeButton("Cancel", (sender, e) => { });
alertDialog = alertBuilder.Create();
alertDialog.Show();
// STACKOVERFLOW LOOK HERE.
//// Calling ForceShowKeyboard does not work here..... Why?
//this.ForceShowKeyboard(editText);
// But, calling ForceShowKeyboard works when in a background thread, sleeping a bit, then run on main thread again
Thread t = new Thread(() => this.DoThreadSTuff(editText));
t.IsBackground = true;
t.Start();
}
private void DoThreadSTuff(EditText editText)
{
// I dont think a sleep is needed, but i found a similar issue in Xamarin.iOS once upon a time, and a sleep was needed. It seems Xamarin.Android doesn't require a sleep though.
//Thread.Sleep(2);
RunOnUiThread(() =>
{
this.ForceShowKeyboard(editText);
});
}
private void ForceShowKeyboard(EditText editText)
{
editText.RequestFocus();
InputMethodManager imm = (InputMethodManager)this.GetSystemService(Android.Content.Context.InputMethodService);
imm.ShowSoftInput(editText, ShowFlags.Implicit);
}
Why the keyboard do not show when you call this.ForceShowKeyboard(editText); directly.
You can find the dialog source code here, when you show a dialog, it will send a SHOW message to handler ,and then let UI thread to show a dialog.
public void show() {
......
sendShowMessage();
}
private void sendShowMessage() {
if (mShowMessage != null) {
// Obtain a new message so this dialog can be re-used
Message.obtain(mShowMessage).sendToTarget();
}
}
.....
mShowMessage = mListenersHandler.obtainMessage(SHOW, listener);
private static final class ListenersHandler extends Handler {
......
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
......
case SHOW:
((OnShowListener) msg.obj).onShow(mDialog.get());
break;
}
}
}
So Dialog.Show() is asynchronous method.
That means this.ForceShowKeyboard(editText); will be called before dialog show. So you can not see the keyboard.
Why the keyboard show when I run the code in the background thread.
You call RunOnUIThread() in another thread. The delegate of RunOnUIThread will be posted to the event queue of the UI thread. That means it will run when you dialog created. So you can see the keyboard.
By checking the source code of RunOnUIThread() it is a also a handler.
public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);
} else {
action.run();
}
}
In other words when your dialog created it will send a message to UI thread handler, and the handler will make EditText focus.
Get the knowledge of Android Handler it will help you to understand.

Not able to execute loop based on thread.sleep

I'm trying to display a series of images from a specific folder in sdcard - in the form of slideshow. filelist[] contains names of all files present in that directory.
I'm filtering out the images here. Next, thread.sleep(1000) does not seem to have any effect. Only the last image in the directory is displayed after a time of 1000ms. Where am I going wrong? Any other way I could accomplish this?
Maybe I've gone completely wrong. I'm a newbie so plz help.
public class List_imgActivity extends Activity {
/** Called when the activity is first created. */
Bitmap[] bitmapArray = new Bitmap[1000];
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button pf=(Button) findViewById(R.id.pick_button);
pf.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
Intent intent = new Intent("org.openintents.action.PICK_DIRECTORY");
intent.setData(Uri.parse("file:///sdcard"));
intent.putExtra("org.openintents.extra.TITLE", "Please select a folder");
intent.putExtra("org.openintents.extra.BUTTON_TEXT", "Use this folder");
startActivityForResult(intent, 1);
}
});
}
protected void onActivityResult(int requestCode, int recievecode, Intent intent)
{
if (requestCode == 1 )
{
Uri uri = intent.getData();
try {
File f=new File(new URI(uri.toString()));
final String nx=f.toString();
if(f.isDirectory()) {
File filelist[] = f.listFiles();
for(int i=0;i<filelist.length;i++)
{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
String filename = filelist[i].getName();
int pos = filename.lastIndexOf(".");
String ext = filename.substring(pos);
if(ext.equals(".jpg"))
{
TextView tv1= (TextView) findViewById(R.id.textView1);
tv1.setText(filelist[i].toString());
ImageView iv1=(ImageView) findViewById(R.id.imageView1);
bitmapArray[i] = BitmapFactory.decodeFile(filelist[i].toString());
iv1.setImageBitmap(bitmapArray[i]);
}
}
}
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
In Android behaviour like this will make the UI-Thread sleep. This will freeze the whole UI of the phone your App will look crashed to the user and the System will automatically kill your application after a while.
There is a mechanism to change things in specific time intervalls. You should use this handlers for doing this. Handlers
A handler has a postDelayed and sendMessageDelayed methods that allow you to either build a Runnable that will be executed after a certain time or send a message that must be handled by the implementation of your handler.
The initialization of the handler would look something like this:
showNextImageHandler = new Handler() {
#Override
public void handleMessage(android.os.Message msg) {
showNextImage();
}
};
showNextImageHandler.sendMessageDelayed(showNextImageHandler.obtainMessage(), 1000);
This code creates a new handler that calls the function showNextImage every time it receives a message. I would store the Handler in an instance variable of your activity to send further messages later on. After the handler is created a first empty message is send in a way that will delay the posting of the message 1000 milliseconds. After a second the showNextImage function will be called. In this function you can change the view and if a next image exists you can post another delayed message to trigger another call to the function later on.
U Must synchronise the current object before applying Thread.sleep() method

Android AsyncTask Dialog Alert

I have a splash screen which check an URL if there's any new content on the server. If show i wish to show a AlertDialog, to the app user so that depending on the action of user,i.e if YES download new contents from the server and get it to database else if NO load the contents for the app from the server.
However i am not being able to use an alert dialog inside AsyncTask
My snippet code is as:
protected String doInBackground(String... mode){
/* I AM QUERY MY DATABASE FOR THE PREVIOUS CONTENT(SAY CONTENT 1, CONTENT 2);
* then i start my connection to the server which has an xml file with the content
* info (say content 3), at this stage .
* i Check certain condition here,
* say if result ==0 then i wish to display an alertdialog.
* I used an alert dialog and i get some error. Stating use Looper or Handler.
* Can anyone help me with this?
*/
}
Edited
So in
doInBackGround(String... mode){
if(result==0){
// how do i implement this alert show that if the dialog appears and on clicking Yes i wish to exectute the URL handling part below
AlertDialog.Builder alert = new AlertDialog.Builder(context);
alert.setTitle("Updates Found");
alert.setMessage( "New Updates for has been found.\n Would you like to download ?\n"
+ "Whats the update: Checking "+pld.result.get(i).get( "issue" ));
alert.setIcon(android.R.drawable.ic_dialog_info);
alert.setPositiveButton(android.R.string.yes,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
try {
URL url = new URL(pld.result.get(i).get("link"));
ManageZipFile.getArchive(url,pld.result.get(i).get("issue"), file);
}
catch (Exception ex) {
Log.d(TAG, "Exception from URL"+ ex.getMessage());
}
progressState += updateProgressBar(20);
pld.saveCoverData(pld.result.get(i).get("issue"));
try {
pldContent = new PullLoadData(getString(R.string.files_path)
+ pld.result.get(i).get("issue")
+ "/contents.xml",context);
pldContent.getNewsItems();
progressState += updateProgressBar(20);
}
catch(XmlPullParserException e) {
Log.e(TAG, "GetNEWSITEM "+ e.getMessage());
}
catch (IOException e) {
Log.e(TAG, "XML FIle not found" + e.getMessage());
}
}
});
alert.setNegativeButton(android.R.string.no,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int arg1) {
dialog.dismiss();
}
});
AlertDialog showAlert = alert.create();
showAlert.show();
}
}
This is because the method doInBackground runs on a non-UI thread, and an AlertDialog needs to be displayed on the UI-thread.
To solve your problem, move the code for your AlertDialog to the method onProgressUpdate in AsyncTask, then when you want to display the Dialog call publishProgress() from doInBackground
protected String doInBackground( String... mode ) {
if( something )
//Conditions for showing a Dialog has been met
}
protected void onProgressUpdate( Void... params ) {
//Show your dialog.
}
If you need to pass some kind of variable/data to the dialog, you can pass the kind of data you declared in extends AsyncTask<Params, Progress, Result> - where Progress is the type of parameter you can pass via the publishProgress( myVariable )-method.
UI thread means it is associated directly with your UI.you cant do operations like network datafetch,disk access etc which require large processing time in your UI thread. They should be done in seperate thread.
AsyncTask helps to carry out theese operations in seperate thread which may otherwise results in infamous ANR error.(application not responding).
AsyncTask contain methods like onPreExecute() onPostExecute() onProgressUpdate() ,doInBackground ()etc you can access UI thread from onPreExecute() onPostExecute() onProgressUpdate() .The operation requiring longer processing time should be carried out in doinbackground().
I can't understand the functionality demands from your question but if you want to display Alert Dialog before data fetching operation,Display it from onPreExecute()
or if you want to display after data fetch Do it from onPostExecute().

how to do dynamic loading in android?

i have an rss feed that comes via an XML. There are several events that are returned with information about them. The events are returned with tags...for eg: ....info...
as soon as i encounter tag, i want to update the listview that i am using to show the events.
So the user does not see the loading progress dialog, rather he sees the events getting added to a list.
How do i do this.
thank you in advance.
Here's pseudo codeish example for one way of doing this using SAX parser;
// MyParserThread is assumed to be inner class of Activity here.
private class MyParserThread extends Thread implements MyParserObserver {
private MyParser mParser;
public MyParserThread() {
mParser = new MyParser();
mParser.setObserver(this);
}
public void run() {
try {
// load xml
mParser.parse(xml);
} catch (Exception ex) {
}
}
public void onMyParserEvent(final DataReceivedFromParsing data) {
runOnUiThread(new Runnable() {
public void run() {
// update data to your UI.
}
});
}
public void cancel() {
mParser.cancel();
}
}
And in your parser you're implementing ContentHandler
public void cancel() {
mCancelled = true;
}
public void startElement(....) {
if (mCancelled) {
// If you want to stop Thread from running, all you have to do
// is make parsing stop.
throw new SAXException("Cancelled");
}
....
}
And triggering parsing once your onCreate is called would be;
public void onCreate(...) {
...
mParserThread = new MyParserThread();
mParserThread.start();
...
}
Now this isn't perfect but hopefully gives some idea how to do Thread handling for this purpose. Fundamentally you just have start it, and adding 'cancel' functionality is somewhat more of a bonus - e.g. for cases in which Activity is destroyed while your Thread is running.

Categories

Resources