Je suis nouveau sur Android et j'essaie d'utiliser UI-Thread. J'ai donc écrit une activité de test simple. Mais je pense avoir mal compris quelque chose, car en cliquant sur le bouton, l'application ne répond plus
public class TestActivity extends Activity {
Button btn;
int i = 0;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btn = (Button)findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
runThread();
}
});
}
private void runThread(){
runOnUiThread (new Thread(new Runnable() {
public void run() {
while(i++ < 1000){
btn.setText("#"+i);
try {
Thread.sleep(300);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}));
}
}
Ci-dessous est l'extrait corrigé de la fonction runThread
.
private void runThread() {
new Thread() {
public void run() {
while (i++ < 1000) {
try {
runOnUiThread(new Runnable() {
@Override
public void run() {
btn.setText("#" + i);
}
});
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
Enveloppez-la simplement en tant que fonction, puis appelez cette fonction à partir de votre fil d’arrière-plan.
public void debugMsg(String msg) {
final String str = msg;
runOnUiThread(new Runnable() {
@Override
public void run() {
mInfo.setText(str);
}
});
}
Vous l'avez à l'envers. Votre clic sur le bouton entraîne l'appel de runOnUiThread()
, mais cela n'est pas nécessaire, car le gestionnaire de clics est déjà en cours d'exécution sur le thread d'interface utilisateur. Ensuite, votre code dans runOnUiThread()
lance un nouveau thread en arrière-plan, dans lequel vous essayez d'effectuer des opérations d'interface utilisateur, qui échouent ensuite.
Au lieu de cela, lancez le fil d’arrière-plan directement à partir de votre gestionnaire de clics. Ensuite, encapsulez les appels à btn.setText()
dans un appel à runOnUiThread()
.
runOnUiThread(new Runnable() {
public void run() {
//Do something on UiThread
}
});
Il existe plusieurs techniques utilisant runOnUiThread (), permet de voir toutes les
Ceci est mon fil principal (fil de l'interface utilisateur) appelé AndroidBasicThreadActivity et je vais le mettre à jour à partir d'un fil de travail de différentes manières -
public class AndroidBasicThreadActivity extends AppCompatActivity
{
public static TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_Android_basic_thread);
textView = (TextView) findViewById(R.id.textview);
MyAndroidThread myTask = new MyAndroidThread(AndroidBasicThreadActivity.this);
Thread t1 = new Thread(myTask, "Bajrang");
t1.start();
}
}
1.) En passant l'instance d'Activity comme argument sur le thread de travail
class MyAndroidThread implements Runnable
{
Activity activity;
public MyAndroidThread(Activity activity)
{
this.activity = activity;
}
@Override
public void run()
{
//perform heavy task here and finally update the UI with result this way -
activity.runOnUiThread(new Runnable()
{
@Override
public void run()
{
AndroidBasicThreadActivity.textView.setText("Hello!! Android Team :-) From child thread.");
}
});
}
}
2.) En utilisant la méthode post de View (Runnable runnable) dans le thread de travail
class MyAndroidThread implements Runnable
{
Activity activity;
public MyAndroidThread(Activity activity)
{
this.activity = activity;
}
@Override
public void run()
{
//perform heavy task here and finally update the UI with result this way -
AndroidBasicThreadActivity.textView.post(new Runnable()
{
@Override
public void run()
{
AndroidBasicThreadActivity.textView.setText("Hello!! Android Team :-) From child thread.");
}
});
}
}
3.) En utilisant la classe Handler du package Android.os Si nous n'avons pas le contexte (this/getApplicationContext ()) ou l'instance d'Activity (AndroidBasicThreadActivity.this), nous devons utiliser la classe Handler en tant que au dessous de -
class MyAndroidThread implements Runnable
{
Activity activity;
public MyAndroidThread(Activity activity)
{
this.activity = activity;
}
@Override
public void run()
{
//perform heavy task here and finally update the UI with result this way -
new Handler(Looper.getMainLooper()).post(new Runnable() {
public void run() {
AndroidBasicThreadActivity.textView.setText("Hello!! Android Team :-) From child thread.");
}
});
}
}
Si vous utilisez fragment, écrivez simplement
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
//Do something on UiThread
}
});
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
gifImageView = (GifImageView) findViewById(R.id.GifImageView);
gifImageView.setGifImageResource(R.drawable.success1);
new Thread(new Runnable() {
@Override
public void run() {
try {
//dummy delay for 2 second
Thread.sleep(8000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//update ui on UI thread
runOnUiThread(new Runnable() {
@Override
public void run() {
gifImageView.setGifImageResource(R.drawable.success);
}
});
}
}).start();
}
Voici comment je l'utilise:
runOnUiThread(new Runnable() {
@Override
public void run() {
//Do something on UiThread
}
});
Vous pouvez utiliser à partir de cet exemple:
Dans l'exemple suivant, nous allons utiliser cette fonction pour publier le résultat d'une recherche Synonym traitée par un fil d'arrière-plan.
Pour atteindre l'objectif lors du rappel d'activité OnCreate, nous allons configurer OnClickListener pour exécuter searchTask sur un thread créé.
Lorsque l'utilisateur clique sur le bouton Rechercher, nous allons créer une classe anonyme Runnable anonyme qui recherche le mot saisi dans R.id.wordEt EditText et démarre le thread Pour exécuter Runnable.
Une fois la recherche terminée, nous allons créer une instance de Runnable SetSynonymResultpour publier le résultat sur le synonyme TextView via le fil de l'interface utilisateur.
Cette technique n’est parfois pas la plus pratique, surtout lorsque nous n’avons pas accès à une instance Activity; Par conséquent, dans les chapitres suivants, nous allons discuter des techniques plus simples et plus propres pour mettre à jour l'interface utilisateur à partir d'une tâche informatique en arrière-plan.
public class MainActivity extends AppCompatActivity {
class SetSynonymResult implements Runnable {
String synonym;
SetSynonymResult(String synonym) {
this.synonym = synonym;
}
public void run() {
Log.d("AsyncAndroid", String.format("Sending synonym result %s on %d",
synonym, Thread.currentThread().getId()) + " !");
TextView tv = (TextView) findViewById(R.id.synonymTv);
tv.setText(this.synonym);
}
}
;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button search = (Button) findViewById(R.id.searchBut);
final EditText Word = (EditText) findViewById(R.id.wordEt);
search.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Runnable searchTask = new Runnable() {
@Override
public void run() {
String result = searchSynomim(Word.getText().toString());
Log.d("AsyncAndroid", String.format("Searching for synonym for %s on %s",
Word.getText(), Thread.currentThread().getName()));
runOnUiThread(new SetSynonymResult(result));
}
};
Thread thread = new Thread(searchTask);
thread.start();
}
});
}
static int i = 0;
String searchSynomim(String Word) {
return ++i % 2 == 0 ? "fake" : "mock";
}
}
La source :
ton ceci:
@UiThread
public void logMsg(final String msg) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
Log.d("UI thread", "I am the UI thread");
}
});
}