web-dev-qa-db-fra.com

Android - Meilleur et sûr moyen d'arrêter le fil

Je veux savoir quel est le meilleur moyen d'arrêter un fil dans Android. Je sais que je peux utiliser AsyncTask à la place et qu'il existe une méthode cancel(). Je dois utiliser Threads dans ma situation. Voici comment j'utilise Thread:

Runnable runnable = new Runnable() {
        @Override
        public void run() {
            //doing some work
        }
    };
new Thread(runnable).start();

Alors, est-ce que quelqu'un a une idée de quel est le meilleur moyen d'arrêter un fil?

68
Android-Droid

Vous devez faire en sorte que votre thread supporte les interruptions. Fondamentalement, vous pouvez appeler yourThread.interrupt() pour arrêter le thread et, dans votre méthode run (), vous devez vérifier périodiquement le statut de Thread.interrupted().

Il y a un bon tutoriel ici .

74
Chris

Cette situation n'est en aucun cas différente de la norme Java. Vous pouvez utiliser la méthode standard pour arrêter un thread:

class WorkerThread extends Thread {
    volatile boolean running = true;

    public void run() {
        // Do work...
        if (!running) return;
        //Continue doing the work
    }
}

L'idée principale est de vérifier la valeur du champ de temps en temps. Lorsque vous devez arrêter votre thread, définissez running sur false. En outre, comme Chris l’a fait remarquer, vous pouvez utiliser le mécanisme d’interruption.

En passant, lorsque vous utilisez AsyncTask, votre approche ne diffère pas beaucoup. La seule différence est que vous devrez appeler la méthode isCancel() depuis votre tâche au lieu d'avoir un champ spécial. Si vous appelez cancel(true) mais n'implémentez pas ce mécanisme, le thread ne s'arrêtera pas tout seul, il ira jusqu'au bout.

27
Malcolm

La méthode Thread.stop() qui pourrait être utilisée pour arrêter un thread est obsolète; pour plus d'informations voir; Pourquoi Thread.stop, Thread.suspend et Thread.resume sont obsolètes? .

Votre meilleur choix est d'avoir une variable que le thread lui-même consulte et quitte volontairement si la variable est égale à une certaine valeur. Vous manipulez ensuite la variable dans votre code lorsque vous souhaitez que le thread se termine. Alternativement bien sûr, vous pouvez utiliser un AsyncTask à la place.

15
Matt

La chose est que vous devez vérifier si le fil est en cours d'exécution ou non !?

Champ:

private boolean runningThread = false;

Dans le fil:

new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        Thread.sleep((long) Math.floor(speed));
                        if (!runningThread) {
                            return;
                        }
                        yourWork();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();

Si vous voulez arrêter le fil, vous devez faire le champ ci-dessous 

private boolean runningThread = false;
2
Hadi Note

Actuellement et malheureusement nous ne pouvons rien faire pour arrêter le fil ....

En ajoutant quelque chose à la réponse de Matt, nous pouvons appeler interrupt() mais cela n'arrête pas le thread ... Indique simplement au système d'arrêter le thread quand le système veut tuer certains threads. Le repos est effectué par le système, et nous pouvons le vérifier en appelant interrupted().

[p.s. : Si vous y allez vraiment avec interrupt(), je vous demanderais de faire quelques expériences avec un court sommeil après avoir appelé interrupt()]

2
Prasham

Il y a 2 manières préférées d’arrêter un thread. 

  1. Créez une variable booléenne volatile et remplacez sa valeur par false et vérifiez à l'intérieur du fil.

    volatile isRunning = false;

    public void run () { if (! isRunning) {return;} }

  2. Ou vous pouvez utiliser la méthode interrupt () qui peut être reçue dans un thread.

    SomeThread.interrupt ();

    public void run () { if (Thread.currentThread.isInterrupted ()) {return;} }

1
Suresh Sharma

J'ai utilisé cette méthode.

Looper.myLooper().quit();

tu peux essayer.

0
Yanchao Wang

S'il y a une classe de thread avec un gestionnaire dans votre projet, la solution est de savoir comment arrêter et éviter de planter l'application lorsque fragment est retiré de la pile.

Ce code est dans Kotlin . Cela fonctionne parfaitement.

class NewsFragment : Fragment() {

    private var mGetRSSFeedsThread: GetRSSFeedsThread? = null

    private val mHandler = object : Handler() {

        override fun handleMessage(msg: Message?) {


            if (msg?.what == GetRSSFeedsThread.GETRSSFEEDSTHREAD_SUCCESS) {
                val updateXMLdata = msg.obj as String
                if (!updateXMLdata.isNullOrEmpty())
                    parseUpdatePager(CommonUtils.getJSONObjectFromXML(updateXMLdata).toString())

            } else if (msg?.what == GetRSSFeedsThread.GETRSSFEEDSTHREAD_SUCCESS) {
                BaseActivity.make_toast(activity, resources.getString(R.string.pleaseTryAgain))
            }

        }
    }
    private var rootview: View? = null;
    override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        rootview = inflater?.inflate(R.layout.fragment_news, container, false);

        news_listView = rootview?.findViewById(R.id.news_listView)
        mGetRSSFeedsThread = GetRSSFeedsThread(this.activity, mHandler)


        if (CommonUtils.isInternetAvailable(activity)) {
            mGetRSSFeedsThread?.start()
        }


        return rootview
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setHasOptionsMenu(true);

    }



    override fun onAttach(context: Context?) {
        super.onAttach(context)
        println("onAttach")
    }

    override fun onPause() {
        super.onPause()
        println("onPause fragment may return to active state again")

        Thread.interrupted()

    }

    override fun onStart() {
        super.onStart()
        println("onStart")

    }

    override fun onResume() {
        super.onResume()
        println("onResume fragment may return to active state again")

    }

    override fun onDetach() {
        super.onDetach()
        println("onDetach fragment never return to active state again")

    }

    override fun onDestroy() {
        super.onDestroy()

        println("onDestroy fragment never return to active state again")
       //check the state of the task
        if (mGetRSSFeedsThread != null && mGetRSSFeedsThread?.isAlive!!) {
            mGetRSSFeedsThread?.interrupt();
        } else {

        }

    }

    override fun onDestroyView() {
        super.onDestroyView()
        println("onDestroyView fragment may return to active state again")



    }

    override fun onStop() {
        super.onStop()
        println("onStop fragment may return to active state again")



    }
}

Le code ci-dessus arrête le thread en cours d'exécution lorsque vous basculez vers un autre fragment ou une activité du fragment actuel. aussi, il recrée quand vous revenez au fragment actuel

0
Suresh Maidaragi

Essayez comme ça

Thread thread = new Thread() {
    @Override
    public void run() {
        Looper.prepare();   
        while(true){ 
            Log.d("Current Thread", "Running"); 
            try{
               Thread.sleep(1000);
            }catch(Exeption Ex){ }
        }
    }
}

thread.start();
thread.interrupt();
0
Udara Kasun

Cela a fonctionné pour moi comme ça. Introduisez une variable statique dans l'activité principale et vérifiez-la régulièrement.

public class MainActivity extends AppCompatActivity {


//This is the static variable introduced in main activity
public static boolean stopThread =false;



  protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Thread thread = new Thread(new Thread1());
    thread.start();

    Button stp_thread= findViewById(R.id.button_stop);

    stp_thread.setOnClickListener(new Button.OnClickListener(){
           @Override
           public void onClick(View v){
              stopThread = true;
           }

     }

  }


  class Thread1 implements Runnable{

        public void run() {

        // YOU CAN DO IT ON BELOW WAY 
        while(!MainActivity.stopThread) {
             Do Something here
        }


        //OR YOU CAN CALL RETURN AFTER EVERY LINE LIKE BELOW

        process 1 goes here;

        //Below method also could be used
        if(stopThread==true){
            return ;
        }
        // use this after every line



        process 2 goes here;


        //Below method also could be used
        if(stopThread==true){
            return ;
        }
        // use this after every line


        process 3 goes here;


        //Below method also could be used
        if(stopThread==true){
            return ;
        }
        // use this after every line


        process 4 goes here;



       }
   }

}
0
Seyon Seyon