Toast à PreferenceActivity est présenté en retard
-
02-10-2019 - |
Question
Je veux montrer un toast juste après que l'utilisateur clique sur un CheckBoxPreference dans mon PreferenceActivity.
myCheckBox.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
Toast.makeText(Prefs.this,
"test",
Toast.LENGTH_SHORT).show();
doSomething();
return false;
}
});
J'ai essayé aussi de mettre le toast dans la méthode doSomething (), mais il est toujours affiché après toute la méthode est traitée. J'ai essayé getBaseContext()
au lieu de Prefs.this
, mais il n'a pas aidé.
Toute idée pourquoi le Toast ne fois pas présenté à la façon de le faire faire?
La solution
Cela se produit parce que l'auditeur de onPreferenceClick
est en cours d'exécution dans le thread d'interface utilisateur. Ce fil est aussi le même que celui qui les poignées affichant la Toast
. Toast#show
pousse seulement un message sur la file d'attente de messages qui exécuter du code alors que l'affichage de Toast
. Cette file d'attente ne sera pas traitée jusqu'à ce que votre gestionnaire de onPreferenceClick
est complètement terminé.
Vous pouvez essayer:
myCheckBox.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
Toast.makeText(Prefs.this,
"test",
Toast.LENGTH_SHORT).show();
Prefs.this.runOnUiThread(new Runnable() {
@Override
public void run() {
doSomething();
}
});
return false;
}
});
Cela entraînera le Toast
à la poste à la file d'attente de messages, votre doSomething
sera également affiché à la file d'attente après le pain grillé. L'inconvénient est qu'il pourrait y avoir des messages UI qui seront traités avant doSomething
est appelée. En outre, si doSomething
est longue marche, il va monopoliser votre thread d'interface utilisateur et pourrait provoquer un proche possible de la force de l'ANR. Vous voudrez peut-être penser à courir doSomething
dans un AsyncTask
si elle prend plus de 150 ms environ.
Autres conseils
Ma solution est d'utiliser la diffusion, et faire un récepteur enregistré dans le manifeste Android.
AndroidManifest:
<receiver android:name=".MyReceiver" >
<intent-filter >
<action android:name="showtoast" />
</intent-filter>
</receiver>
broadcasts:
public static void BroadcastMessage(Context context, Bundle extra)
{
Intent intent = new Intent();
intent.setPackage(context.getPackageName());
intent.setAction("showtoast");
if (extra != null)
intent.putExtras(extra);
context.sendBroadcast(intent);
}
récepteur comme ci-dessous:
public class MyReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
if ("showtoast".equalsIgnoreCase(intent.getAction()) && (bundle != null)
{
String title = bundle.getString("title", "");
View view;
TextView mTextView;
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.my_toast_layout, null);
mTextView = (TextView) view.findViewById(R.id.tv_title);
mTextView.setText(title);
Toast toast = new Toast(context.getApplicationContext());
toast.setGravity(Gravity.CENTER, 0, 0);
toast.setView(view);
toast.setDuration(Toast.LENGTH_LONG);
toast.show();
}
}
}