简体   繁体   中英

How to get access to the MainActivity findViewById from inside a Broadcast Receiver onReceive method?

When I use this code:

@Override
public void onReceive(Context context, Intent intent) {

    seconds += 0.1;

    if (seconds > 59.9) {
        seconds=0;
        minutes++;
    }

    TextView tv = (TextView)((MainActivity)context).findViewById(R.id.txtChron);
    tv.setText (String.valueOf(minutes) + ":" + String.valueOf(seconds));
}

I get an error when trying to cast the context to MainActivity .

Here is the error / stack trace:

E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.jordanbleu.lab8chronservjordanbleu, PID: 22693 java.lang.RuntimeException: Error receiving broadcast Intent { act=com.example.jordanbleu.lab8chronservjordanbleu.MY_TIME_TICK flg=0x10 } in com.example.jordanbleu.lab8chronservjordanbleu.ChronometerReceiver@d9365fe at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:1132) at android.os.Handler.handleCallback(Handler.java:751) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6119) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776) Caused by: java.lang.ClassCastException: android.app.Application cannot be cast to com.example.jordanbleu.lab8chronservjordanbleu.MainActivity at com.example.jordanbleu.lab8chronservjordanble u.ChronometerReceiver.onReceive(ChronometerReceiver.java:41) at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:1122) at android.os.Handler.handleCallback(Handler.java:751) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6119) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)

So I have a MainActivity , which starts a service. The service creates a new thread, and this thread constantly created implicit intents which are handled by a BroadcastReceiver . This broadcast receiver will update a clock, and update a TextView in the layout with the updated time. But when I try to get access to the findViewByID via the context parameter, I get the error above.

Initialize your TextView inside the onCreate function of your Activity .

TextView tv = (TextView) findViewById(R.id.txtChron);

Then in your onReceive function

@Override
public void onReceive(Context context, Intent intent) {
    seconds += 0.1;
    if (seconds > 59.9) {
        seconds=0;
        minutes++;
    }

    tv.setText(String.valueOf(minutes) + ":" + String.valueOf(seconds));
}

Your error is:

java.lang.ClassCastException: android.app.Application cannot be cast to com.example.jordanbleu.lab8chronservjordanbleu.MainActivity

This means "Context context" is Application, not the MainActivity.

My suggestion is, inflate your TextView in OnCreate.

TextView tv;

@Override
public void onCreate(Bundle savedInstanceState) {
    tv = (TextView) findViewById(R.id.txtChron); // This!
...
}

@Override
public void onReceive(Context context, Intent intent) {

    seconds += 0.1;

    if (seconds > 59.9) {
        seconds=0;
        minutes++;
    }

    tv.setText (String.valueOf(minutes) + ":" + String.valueOf(seconds));
}

You may also use an interface. This way you will not have to access The UI element in the BroadcastReceiver.

1) Create an interface:

interface ReceiverListener {
    public void doSomething(String arg1, String arg2);
}

2) Instantiate the Listener in your BroadcastReceiver

public class YourBroadCastReceiver extends BroadCastReceiver{

    private ReceiverListener listener;

    @Override
    public void onReceive(Context context, Intent intent) {

        listener = (ReceiverListener)context;  // Initialize listener 

        // Your logic 
        String minutes = //get it
        String seconds = // get it

       listener.doSomething(minutes,seconds); 

    }

}

3) Implement the interface in Your Activity and override the method

public YourActivity extends AppcompatActivity implements ReceiverListener{

     // Activity related code
    TextView tv;

    public void updateUI(String minutes,String seconds){
        tv.setText (minutes + ":" + seconds);
    }


    @Override 
    public void doSomething(String arg1, String arg2){
        updateUI(arg1,arg2);
    }

}

Relevant Link:

If you want to see the advantage of using an interface in this case, READ THIS

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