web-dev-qa-db-fra.com

Android BroadcastReceiver onReceive Update TextView dans MainActivity

Dans MainActivity, j'ai un TextView: textV1. J'ai aussi une méthode dans MainActivity qui met à jour cette textview:

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

Dans BroadcasrReceiver, je dois mettre à jour le texte de textV1 dans MainActivity.

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
    }
}

Comment cela peut-il être fait? BroadcastReceiver est exécuté à partir d'un service. Ce code je ne peux pas changer. Puis-je accéder à textV1 dans MainActivity et le modifier à partir de onReceive ()? J'ai essayé beaucoup de choses mais toutes échouent.

14
user3499199

Dans votre MainActivity, initialisez une variable de la classe MainActivity comme ci-dessous.

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) {

        }           
    }
}
34
User10001

créez une instance de la classe, puis transmettez la valeur à la fonction qui modifie la valeur TextView en procédant comme suit: dans votre méthode BroadcastReceiver overRide onReceive et collez-les comme vous le souhaitez

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);
        }
    }
});

maintenant, nous expliquons updateTheTextView et inst dans la classe YourActivityToUpdate. Collez ces lignes s'il vous plait.

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;
}

et c'est la méthode updateTheTextView qui doit être placée dans la classe YourActivityToUpdate

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

je pense que c'est une meilleure façon grâce à "kevin-lynx"

2
ShahinFasihi

Si quelqu'un recherche cette solution exacte, mais à Kotlin, procédez comme suit:

class MainActivity : AppCompatActivity() {

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

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

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ins = this;     
    }

    fun updateTheTextView(t: String) {
        [email protected] {
            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) {

        }
    }
}
0
Renato Aloi

Utiliser l'interface

Une autre façon de gérer cette situation consiste à utiliser une interface. Je décrirai l'avantage d'utiliser cette approche, mais voyons d'abord comment cela se fait.

Suivez ces étapes:
1) Créer une interface

public interface MyBroadcastListener{

    public void doSomething(String result);

}

2) Initialiser l'auditeur dans 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) Implémenter l'interface dans Activity et remplacer la méthode

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
    }

 }

Avantage d'utiliser l'interface?

  • Lorsque vous avez BroadcastReceiver dans un fichier différent
  • BroadcastReceiver découplé

L'utilisation de l'interface rend BroadcastReceiver indépendant de toute activité. Disons à l'avenir que vous souhaitez utiliser ce BroadCastReceiver avec une autre activité qui prend le résultat de BroadcastReceiver et commence une DetailActivity avec le résultat. C'est une tâche complètement différente, mais vous utiliserez Same BroadcastReceiver sans même changer le code à l'intérieur de BroadcastReceiver.

Comment faire ça?
Implémentez l'interface dans l'activité et substituez la méthode. C'est tout!

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
    }

 }
0
Rohit Singh