简体   繁体   中英

android - calling ui thread from worker thread

Hi I want to make Toast available to me no-matter-what and available from any thread whenever I like within my application. So to do this I extended the Activity class:

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.widget.Toast;

public class MyActivity extends Activity{
    private Handler mHandler;

    @Override   
    public void onCreate(Bundle savedInstanceState) {       
        mHandler = new Handler();
        super.onCreate(savedInstanceState);
    }

    private class ToastRunnable implements Runnable {
        String mText;

        public ToastRunnable(String text) {
            mText = text;
        }

        public void run(){
           Toast.makeText(getApplicationContext(), mText, Toast.LENGTH_SHORT).show();
        }
    }

    public void doToast(String msg) {
        mHandler.post(new ToastRunnable(msg));
    }
}

so that all Activity classes in my app are now simply

public class AppMain extends MyActivity {
   //blah
}

what I expected to be able to do (in a worker thread) was this:

try{
   MyActivity me = (MyActivity) Looper.getMainLooper().getThread();
   me.doToast("Hello World");
}
catch (Exception ex){
   Log.e("oh dear", ex.getMessage());
}

and so long as the Activity was a " MyActivity " it should work - but the problem is ---> the Looper.getMainLooper().getThread(); isn't returning the MyActivity to me and it's making me cry - what am I doing wrong?

: EDIT :

some background to explain "why" I am stuck with this type of implmentation.

I need to be able to confirm to the user that a "HTTP POST" event has been a success. Now. If the User clicks "OK" on the UI Form it MAY or MAY NOT have internet at that time.. If it has Internet - all well and good - it posts the form via HTTP POST all well and good .. but if there is NO Internet most (99.999% of Android apps lame /pathetic / mewling at this, and basically offer the user no plan "b" assuming that at all times the internet is there - when it is NOT)

My App will not "go lame (as I call it)" - it does have a plan "b" instead it "Queues" the post event and retries every x minutes.. now this is a silent thread in the background.. I have plenty of user interaction all over the app I don't know where the user will "be" but eventually when the HTTP POST that queue/retries/queue/retries returns "! Success! " I want to Toast that as a message to the user (EG: "your form was sent")

What's wrong with runOnUiThread ?

http://developer.android.com/reference/android/app/Activity.html#runOnUiThread(java.lang.Runnable )

activity.runOnUiThread(new Runnable() {
    public void run() {
        Toast.makeText(activity, "Hello, world!", Toast.LENGTH_SHORT).show();
    }
});

use below code. create activity object which contains your activity instance..

activity.runOnUiThread(new Runnable() {
  public void run() {
    Toast.makeText(activity.getApplicationContext(),"Toast text",Toast.LENGTH_SHORT).show();
  }
);

This will allow you to display the message without needing to rely on the context to launch the toast, only to reference when displaying the message itself.

runOnUiThread was not working from an OpenGL View thread and this was the solution. Hope it helps.

private Handler handler = new Handler();
handler.post(new Runnable() {
    public void run() {
        Toast.makeText(activity, "Hello, world!", Toast.LENGTH_SHORT).show();
    }
});

You can't just cast the result of getThread() to an instance of your MyActivity base class. getThread() returns a Thread which has nothing to do with Activity .

There's no great -- read: clean -- way of doing what you want to do. At some point, your "worker thread" abstraction will have to have a reference to something that can create a Toast for you. Saving off some static variable containing a reference to your Activity subclass simply to be able to shortcut Toast creation is a recipe for memory leaks and pain.

Why don't you send an intent that is captured by a BroadCastReceiver, then the broadcast receiver can create a notification in the notification tray. It's not a toast, but its a way to inform the user that his post has been successful.

如果它在你自己的活动中,为什么你不能只调用doToast()

if you have the context with you, you can call the ui thread like this from non activity class.

((Activity)context).runOnUiThread(new Runnable() {
    public void run() {
        // things need to work on ui thread
    }
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM