Toast не будет отображаться перед try / catch Thread.sleep()

#android #sleep #toast

#Android #сон #toast

Вопрос:

У меня возникла любопытная проблема, когда я пытаюсь show(); мои тосты. Ниже вы увидите два тоста, разделенных try/catch and Thread.sleep(); В этом случае второй тост, toast2 , будет отображаться, но toast1 не будет.

Если я удалю try/catch оба тоста, они будут отображаться без проблем.

Я видел в другом месте, что toast.show(); делает запрос в потоке пользовательского интерфейса, который может противоречить другим операциям. Мне интересно, является ли это той же проблемой, что и у меня здесь с Thread.sleep(); Как я могу решить эту проблему?

Спасибо

TestService.java

     ///Debug - Show a Toast
    // Toast does NOT show up
    Toast toast1 = Toast.makeText(context,"Service Started", Toast.LENGTH_SHORT);
    toast1.show();

    //Try to sleep for roughly 2 seconds
    try {
        Thread.sleep(2000);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    //Debug - Shows a Toast
    Toast toast2 = Toast.makeText(context,"Sleep completed", Toast.LENGTH_SHORT);
    toast2.show();
  

Комментарии:

1. Выполняется ли это в потоке пользовательского интерфейса?

2. что вы пытаетесь сделать?? вы хотите, чтобы поток пользовательского интерфейса ждал 2 секунды? или вы хотите, чтобы ваш поток управления ждал 2 секунды, что вам нужно??

3. Сначала изучите основы пользовательского интерфейса

Ответ №1:

В реальной жизни у вас, вероятно, будет какая-то логика вместо простого «сна», верно? Согласно вашему примеру, правильным способом запуска службы для Android было бы выполнение ее в рабочем потоке. Это гарантирует, что вы не получите ANR.

ваш мог бы выглядеть примерно так:

     new AsyncTask<Void, Void, Void>() {

        @Override
        protected void onPostExecute(Void result) {
            Toast toast2 = Toast.makeText(context, "Sleep completed",
                    Toast.LENGTH_SHORT);
            toast2.show();
        }

        @Override
        protected void onPreExecute() {
            Toast toast1 = Toast.makeText(context, "Service Started",
                    Toast.LENGTH_SHORT);
            toast1.show();
        }

        @Override
        protected Void doInBackground(Void... params) {
            // Try to sleep for roughly 2 seconds
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return null;

        }

    }.execute();
  

Ответ №2:

Поскольку вы приостанавливаете поток пользовательского интерфейса сразу после первого тоста, у него нет возможности отображаться. И к тому времени, как режим ожидания закончится, время для первого тоста прошло.

Это звучит как наиболее правдоподобное объяснение, но я могу ошибаться. Нужно действительно глубоко покопаться в коде Android, чтобы узнать наверняка.

Комментарии:

1. Я считаю, что вы правы. Я сократил время почти до нуля и toast1 появился.

Ответ №3:

Я предполагаю, что вам нужно создать тост, который длится более 2 секунд (почему вы должны использовать Thread.Sleep(2000) перед отправкой другого тоста?).
Итак, я только что нашел эту ссылку, которая предоставляет очень хороший пример.
Надеюсь, это поможет

Ответ №4:

Я столкнулся с той же проблемой, я попытаюсь решить с помощью AsyncTask, как предложено, но мой вариант использования следующий:

1) Я хочу отобразить всплывающее сообщение (начать широковещательное сообщение) 2) Если условие выполнено правильно, я передаю message1 клиентам. 3) Я сплю 2 секунды, чтобы разрешить трансляцию для завершения. 4) Я постоянно отправляю message2 клиентам. 5) Если это будет сделано, я бы поджарил другое сообщение (широковещательные сообщения завершены)

Я придумал следующий пример обходного пути (хотя последовательность всплывающих сообщений все еще отображалась в обратном порядке):

 package com.toasttester;

import android.os.Handler;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
import android.os.AsyncTask;

public class MainActivity extends ActionBarActivity {
    Handler handler = new Handler();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);
        PreSleepToast pst = new PreSleepToast();
        pst.execute();
        Toast t = Toast.makeText(getApplicationContext(), "Message1", Toast.LENGTH_SHORT);
        t.show();
        try {
            Thread.sleep(2000);//to allow broadcasting to complete
        } catch (Exception e) {
            e.printStackTrace();
        }
        callToast1();
    }
    private Runnable r = new Runnable() {
        @Override
        public void run() {
            Toast t = Toast.makeText(getApplicationContext(), "Message3", Toast.LENGTH_SHORT);
            t.show();
        }
     };

    public class PreSleepToast extends AsyncTask<Void, byte[], Void> {
        /**
         * The sender socket on which we send connections.
         */
        public PreSleepToast() {
        }

        /**
         * Polling loop for outgoing connections.
         */
        @Override
        protected Void doInBackground(Void... params) {
            handler.post(r);
            return null;
        };
    };

    public void callToast1(){
        Toast t = Toast.makeText(getApplicationContext(), "Message2", Toast.LENGTH_SHORT);
        t.show();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}
  

Комментарии:

1. хм, мое решение работает только на marshmallow, не сработало на nougat….in кажется, что nougat заменяет «Message2» …. тогда как в marshmallow он отображается после него.

2. теперь я озадачен поведением nougat ….. даже если я использую ArrayList для постановки в очередь моих Message1 и Message2 по одному до сна и по одному после ….. и затем я запускаю asynctask, который публикует runnable, который в конечном итоге перебирает сообщения в ArrayList, чтобы поджарить их …… но все равно отображается только последнее сообщение……