简体   繁体   English

Android BroadcastReceiver onReceive 更新 MainActivity 中的 TextView

[英]Android BroadcastReceiver onReceive Update TextView in MainActivity

In MainActivity I have a TextView: textV1.在 MainActivity 我有一个 TextView:textV1。 I also have a method in MainActivity that updates that textview:我在 MainActivity 中还有一个方法可以更新该文本视图:

public void updateTheTextView(final String t) {
    MainActivity.this.runOnUiThread(new Runnable() {
        public void run() {
            TextView textV1 = (TextView) findViewById(R.id.textV1);
            textV1.setText(t);
        }
    });
}

In a BroadcasrReceiver I need to update the text in textV1 in MainActivity.在 BroadcasrReceiver 中,我需要更新 MainActivity 中 textV1 中的文本。

public class NotifAlarm extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
            // other things done here like notification

            // NEED TO UPDATE TEXTV1 IN MAINACTIVITY HERE
    }
}

How can this be done?如何才能做到这一点? The BroadcastReceiver is run from a service. BroadcastReceiver 从服务运行。 This code I cannot change.此代码我无法更改。 Can I access and change textV1 in MainActivity from onReceive()?我可以从 onReceive() 访问和更改 MainActivity 中的 textV1 吗? I've tried many things but all fail.我尝试了很多东西,但都失败了。

In your MainActivity initialize a variable of MainActivity class like below.在您的MainActivity初始化MainActivity类的变量,如下所示。

public class MainActivity extends Activity {
    private static MainActivity ins;
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ins = this;     
    }

    public static MainActivity  getInstace(){
        return ins;
    }

    public void updateTheTextView(final String t) {
        MainActivity.this.runOnUiThread(new Runnable() {
            public void run() {
                TextView textV1 = (TextView) findViewById(R.id.textV1);
                textV1.setText(t);
            }
        });
    }
}


public class NotifAlarm extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        try {
            MainActivity  .getInstace().updateTheTextView("String");
        } catch (Exception e) {

        }           
    }
}

#Use Interface Another way to deal with this situation is by using an Interface. #Use Interface 处理这种情况的另一种方法是使用接口。 I will describe the advantage of this approach but first, let's see how it's done.我将描述这种方法的优点,但首先,让我们看看它是如何完成的。

Follow these steps:按着这些次序:
1) Create an interface 1)创建接口

public interface MyBroadcastListener{

    public void doSomething(String result);

}

2) Initialize the listener in BroadCastReceiver 2) 在 BroadCastReceiver 中初始化监听器

public class NotifAlarm extends BroadcastReceiver {

    private MyBroadcastListener listener;

    @Override
    public void onReceive(Context context, Intent intent) {
       
        listener = (MyBroadcastListener)context;

        // other things done here like notification

        // NUPDATE TEXTV1 IN MAINACTIVITY HERE
        listener.doSomething("Some Result");
    }
}

3) Implement the interface in Activity and override the method 3)在Activity中实现接口并覆盖方法

public YourActivity extends AppCompatActivity implements MyBroadcastListener{

    // Your Activity code 

    public void updateTheTextView(String t) {
        TextView textV1 = (TextView) findViewById(R.id.textV1);
        textV1.setText(t);
    }

    @Override
    public void doSomething(String result){
         updateTheTextView(result);          // Calling method from Interface
    }

 }

##Advantages of using the interface? ##使用界面的好处?

  • When you have BroadcastReceiver in a different file当您在不同的文件中有 BroadcastReceiver 时
  • Decoupled BroadcastReceiver解耦广播接收器

Using an interface makes BroadcastReceiver independent of any Activity.使用接口使 BroadcastReceiver 独立于任何 Activity。 Let's say in future you want to use this BroadCastReceiver with another Activity which takes the result from BroadcastReceiver and start a DetailActivity.假设将来您想将此 BroadCastReceiver 与另一个 Activity 一起使用,该 Activity 从 BroadcastReceiver 获取结果并启动 DetailActivity。 This is completely a different task but you will use the same BroadcastReceiver without even a single code change inside BroadcastReceiver.这是一个完全不同的任务,但您将使用相同的 BroadcastReceiver,而无需更改 BroadcastReceiver 中的任何代码。

How to do that?怎么做?
Implement the interface in the Activity and Override the method.在Activity中实现接口并覆盖方法。 That's it!就是这样!

public ListActivity extends AppCompatActivity implements MyBroadcastListener{

    // Your Activity code 

    public void startDetailActivity(String title) {
        Intent i = new Intent(ListActivity,this, DetailActivity.class);
        i.putExtra("Title", title);
        startActivity(i);
    }

    @Override
    public void doSomething(String result){
         startDetailActivity(String title);    // Calling method from Interface
    }

 }

create an instance of the class and then pass the value to the function that changes TextView value follow these steps please : in your BroadcastReceiver overRide onReceive method and paste These lines or changes theme as you wish创建该类的实例,然后将值传递给更改 TextView 值的函数,请按照以下步骤操作:在您的 BroadcastReceiver 中覆盖 onReceive 方法并根据需要粘贴这些行或更改主题

private Handler handler = new Handler(); // Handler used to execute code on the UI thread
// Post the UI updating code to our Handler
handler.post(new Runnable() {
    @Override
    public void run() {
    //Toast.makeText(context, "Toast from broadcast receiver", Toast.LENGTH_SHORT).show();
    YourActivityToUpdate.updateTheTextView(message);
    YourActivityToUpdateinst = YourActivityToUpdate.instance();
        if(inst != null)  { // your activity can be seen, and you can update it's context
        inst.updateTheTextView(message);
        }
    }
});

now we explain the updateTheTextView and inst in YourActivityToUpdate class Paste these Lines please现在我们解释一下 YourActivityToUpdate 类中的 updateTheTextView 和 inst 请粘贴这些行

private static SignUpVerify mInst;

public static SignUpVerify instance() {
        return mInst;
}
@Override
public void onStart() {
    super.onStart();
    mInst = this;
}

@Override
public void onStop() {
    super.onStop();
    mInst = null;
}

and this is the updateTheTextView method that should be placed in YourActivityToUpdate class这是应该放在 YourActivityToUpdate 类中的 updateTheTextView 方法

public void updateTheTextView(final String verifyCodeValue) {
                Log.i("verifyCodeValue", verifyCodeValue);
                YourTextViewToUpdate.setText(verifyCodeValue);
    }

i think this is a better way thanks to "kevin-lynx"由于“kevin-lynx”,我认为这是一个更好的方法

If someone is searching this exact solution, but in Kotlin, do the following:如果有人正在搜索这个确切的解决方案,但在 Kotlin 中,请执行以下操作:

class MainActivity : AppCompatActivity() {

    companion object {
        var ins: MainActivity? = null
        fun getInstance(): MainActivity? {
            return ins
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        ins = this
    }

    fun updateTheTextView(t: String) {
        this@MainActivity.runOnUiThread {
            val textV1 = findViewById<TextView>(R.id.textV1)
            textV1.text = t
        }
    }
}

class NotifAlarm : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        try {
            MainActivity.getInstance()?.updateTheTextView("The String")
        } catch (e: Exception) {

        }
    }
}

In your broadcastreceiver class send broadcast在您的广播接收器类中发送广播

public class mybroadcaster extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
    context.sendBroadcast(new Intent("updatetext"));
  }
}

In your activity register your broadcastreceiver and call it, do your work at onReceive and unregister the broadcaster in onDestroy()在您的活动中注册您的广播接收器并调用它,在onReceive完成您的工作并在onDestroy()取消注册广播器

public class MyActivity  extends Activity{

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    registerReceiver(broadcastReceiver, new IntentFilter("updatetext"));
}

BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        // do your work here
    }
};

@Override
protected void onDestroy() {
    super.onDestroy();
    unregisterReceiver(broadcastReceiver);
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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