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 Thread
s 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?
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 .
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.
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.
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;
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()
]
Il y a 2 manières préférées d’arrêter un thread.
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;} }
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;} }
J'ai utilisé cette méthode.
Looper.myLooper().quit();
tu peux essayer.
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
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();
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;
}
}
}