Fatal Exception при попытке обновить панель progress [duplicate]

== выполняет контрольную проверку равенства, ссылаясь на то, что 2 объекта (строки в этом случае) относятся к одному и тому же объекту в памяти.

Метод equals() будет проверять, будет ли содержимое или состояния двух объектов одинаковы.

Очевидно, что == работает быстрее, но во многих случаях может (может) давать ложные результаты, если вы просто хотите сказать, имеет ли 2 String s тот же текст.

Определенно рекомендуется использовать метод equals().

Не беспокойтесь о производительности. Некоторые способы поощрения использования String.equals():

  1. Реализация String.equals() сначала проверяет ссылочное равенство (используя ==), и если две строки одинаковы по ссылке, дальнейший расчет Выполняется!
  2. Если 2 ссылки на строки не совпадают, String.equals() будет проверять длину строк. Это также является быстрой операцией, поскольку класс String хранит длину строки, не нужно считать символы или кодовые точки. Если длины отличаются, дальнейшая проверка не выполняется, мы знаем, что они не могут быть равными.
  3. Только если мы доберемся до этого, будет фактически сопоставлено содержимое двух строк, и это будет короткий сравнение: не все символы будут сравниваться, если мы найдем несоответствующий символ (в том же положении в 2 строках), никакие другие символы не будут проверены.

Когда все сказано и даже если у нас есть гарантия, что строки являются стажерами, использование метода equals() все еще не является издержками, которые можно было бы подумать, определенно рекомендуемым способом. Если вам нужна эффективная проверка ссылок, используйте перечисления, где гарантируется спецификацией и реализацией языка, что одно и то же значение перечисления будет одним и тем же объектом (по ссылке).

748
задан Cœur 10 December 2017 в 18:10
поделиться

12 ответов

Используйте этот код, и нет необходимости в функции runOnUiThread:

private Handler handler;
private Runnable handlerTask;

void StartTimer(){
    handler = new Handler();   
    handlerTask = new Runnable()
    {
        @Override 
        public void run() { 
            // do something  
            textView.setText("some text");
            handler.postDelayed(handlerTask, 1000);    
        }
    };
    handlerTask.run();
}
3
ответ дан Allan Pereira 15 August 2018 в 21:54
поделиться

Это трассировка стека упомянутого исключения

        at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6149)
        at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:843)
        at android.view.View.requestLayout(View.java:16474)
        at android.view.View.requestLayout(View.java:16474)
        at android.view.View.requestLayout(View.java:16474)
        at android.view.View.requestLayout(View.java:16474)
        at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:352)
        at android.view.View.requestLayout(View.java:16474)
        at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:352)
        at android.view.View.setFlags(View.java:8938)
        at android.view.View.setVisibility(View.java:6066)

Итак, если вы идете и копаете, вы узнаете

void checkThread() {
    if (mThread != Thread.currentThread()) {
        throw new CalledFromWrongThreadException(
                "Only the original thread that created a view hierarchy can touch its views.");
    }
}

Где mThread инициализируется в конструкторе, как показано ниже

mThread = Thread.currentThread();

Все, что я хочу сказать, когда мы создали конкретное представление, мы создали его в потоке пользовательского интерфейса, а затем попытаемся изменить его в Worker Thread.

Мы можем проверить его ниже фрагмент кода

Thread.currentThread().getName()

, когда мы раздуваем макет и позже, когда вы получаете исключение.

1
ответ дан Amit Yadav 15 August 2018 в 21:54
поделиться

Для меня проблема заключалась в том, что я явно вызывал onProgressUpdate() из моего кода. Это не должно быть сделано. Вместо этого я вызвал publishProgress() и решил эту ошибку.

0
ответ дан ann 15 August 2018 в 21:54
поделиться

Вы можете использовать Handler для удаления View, не нарушая основной поток пользовательского интерфейса. Вот пример кода

new Handler(Looper.getMainLooper()).post(new Runnable() {
                                                        @Override
                                                        public void run() {
                                                           //do stuff like remove view etc
                                                            adapter.remove(selecteditem);
                                                        }
                                                    });
1
ответ дан Bilal Mustafa 15 August 2018 в 21:54
поделиться

Я вижу, что вы приняли ответ @ Provence. На всякий случай, вы также можете использовать обработчик! Во-первых, сделайте int-поля.

    private static final int SHOW_LOG = 1;
    private static final int HIDE_LOG = 0;

Затем создайте экземпляр обработчика в качестве поля.

    //TODO __________[ Handler ]__________
    @SuppressLint("HandlerLeak")
    protected Handler handler = new Handler()
    {
        @Override
        public void handleMessage(Message msg)
        {
            // Put code here...

            // Set a switch statement to toggle it on or off.
            switch(msg.what)
            {
            case SHOW_LOG:
            {
                ads.setVisibility(View.VISIBLE);
                break;
            }
            case HIDE_LOG:
            {
                ads.setVisibility(View.GONE);
                break;
            }
            }
        }
    };

Сделайте метод.

//TODO __________[ Callbacks ]__________
@Override
public void showHandler(boolean show)
{
    handler.sendEmptyMessage(show ? SHOW_LOG : HIDE_LOG);
}

Наконец, поставьте это на метод onCreate().

showHandler(true);
6
ответ дан David Dimalanta 15 August 2018 в 21:54
поделиться

При использовании AsyncTask Обновление пользовательского интерфейса в методе onPostExecute

    @Override
    protected void onPostExecute(String s) {
   // Update UI here

     }
0
ответ дан Deepak Kataria 15 August 2018 в 21:54
поделиться

Обычно любое действие, связанное с пользовательским интерфейсом, должно выполняться в основном потоке или потоке пользовательского интерфейса, то есть в том, что выполняется onCreate() и обработка событий. Один из способов убедиться в этом: runOnUiThread () , другой - обработчики.

ProgressBar.setProgress() имеет механизм, для которого он всегда будет выполняться в основном потоке, поэтому поэтому он работал.

См. Нержавеющая резьба .

22
ответ дан hoss 15 August 2018 в 21:54
поделиться

Я был в этой ситуации, но нашел решение с объектом Handler.

В моем случае я хочу обновить ProgressDialog с помощью шаблона наблюдателя . Мой просмотр реализует observer и отменяет метод обновления.

Итак, мой основной поток создает представление, а другой поток вызывает метод обновления, который обновляет ProgressDialop и ....:

Только исходный поток, создавший иерархию представлений, может коснуться его представлений.

Можно решить проблему с объектом Handler.

Ниже, различные части мой код:

public class ViewExecution extends Activity implements Observer{

    static final int PROGRESS_DIALOG = 0;
    ProgressDialog progressDialog;
    int currentNumber;

    public void onCreate(Bundle savedInstanceState) {

        currentNumber = 0;
        final Button launchPolicyButton =  ((Button) this.findViewById(R.id.launchButton));
        launchPolicyButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                showDialog(PROGRESS_DIALOG);
            }
        });
    }

    @Override
    protected Dialog onCreateDialog(int id) {
        switch(id) {
        case PROGRESS_DIALOG:
            progressDialog = new ProgressDialog(this);
            progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            progressDialog.setMessage("Loading");
            progressDialog.setCancelable(true);
            return progressDialog;
        default:
            return null;
        }
    }

    @Override
    protected void onPrepareDialog(int id, Dialog dialog) {
        switch(id) {
        case PROGRESS_DIALOG:
            progressDialog.setProgress(0);
        }

    }

    // Define the Handler that receives messages from the thread and update the progress
    final Handler handler = new Handler() {
        public void handleMessage(Message msg) {
            int current = msg.arg1;
            progressDialog.setProgress(current);
            if (current >= 100){
                removeDialog (PROGRESS_DIALOG);
            }
        }
    };

    // The method called by the observer (the second thread)
    @Override
    public void update(Observable obs, Object arg1) {

        Message msg = handler.obtainMessage();
        msg.arg1 = ++currentPluginNumber;
        handler.sendMessage(msg);
    }
}

Это объяснение можно найти на на этой странице , и вы должны прочитать «Пример ProgressDialog со вторым потоком».

19
ответ дан Jonathan 15 August 2018 в 21:54
поделиться

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

Мое решение: мне нужно удалить <requestFocus /> из EditText в XML.

0
ответ дан Peter Mortensen 15 August 2018 в 21:54
поделиться
  • 1
    работал как шарм. для меня единственная проблема здесь в том, что я хотел сделать error.setText(res.toString()); внутри метода run (), но я не мог использовать res, потому что он не был окончательным .. слишком плохо – noloman 1 August 2011 в 13:31
  • 2
    Один краткий комментарий по этому поводу. У меня был отдельный поток, который пытался изменить пользовательский интерфейс, и этот код работал, но у меня был вызов runOnUiThread из объекта Activity. Я должен был сделать что-то вроде myActivityObject.runOnUiThread(etc) – Kirby 17 February 2012 в 23:27
  • 3
    @Kirby Спасибо за эту рекомендацию. Вы можете просто выполнить «MainActivity.this», и он должен работать так, чтобы вам не приходилось ссылаться на ваш класс активности. – JRomero 5 April 2013 в 15:37
  • 4
    Мне потребовалось некоторое время, чтобы понять, что runOnUiThread() - метод Деятельности. Я использовал код в фрагменте. Я закончил делать getActivity().runOnUiThread(etc), и это сработало. Фантастика!; – lejonl 19 August 2013 в 21:07
  • 5
    Можем ли мы остановить выполнение задачи, которая написана в теле метода runOnUiThread? – Karan Sharma 4 September 2014 в 21:18
  • 6
    Ошибка: (73, 67) ошибка: нестатический метод set (String) не может ссылаться на статический контекст – user 1 December 2015 в 17:33
  • 7
    У меня такая же проблема с моими тестовыми классами. Это работало для меня как прелесть. Однако, заменив runOnUiThread на runTestOnUiThread. благодаря – DaddyMoe 21 February 2016 в 18:45
  • 8
    Отлично .. Он будет работать везде. – Learning Always 15 February 2018 в 05:36
  • 9
    это лучший ответ, спасибо – R.jzadeh 20 July 2018 в 13:31
  • 10
    @ R.jzadeh приятно это слышать. С того момента, как я написал этот ответ, возможно, теперь вы можете сделать это лучше :) – Błażej 20 July 2018 в 19:02

Я решил это, поставив runOnUiThread( new Runnable(){ .. внутри run():

thread = new Thread(){
        @Override
        public void run() {
            try {
                synchronized (this) {
                    wait(5000);

                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            dbloadingInfo.setVisibility(View.VISIBLE);
                            bar.setVisibility(View.INVISIBLE);
                            loadingText.setVisibility(View.INVISIBLE);
                        }
                    });

                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Intent mainActivity = new Intent(getApplicationContext(),MainActivity.class);
            startActivity(mainActivity);
        };
    };  
    thread.start();
110
ответ дан Seth 15 August 2018 в 21:54
поделиться
  • 1
    Это потрясло. Благодарим за информацию, что это также можно использовать внутри любого другого потока. – Nabin 16 March 2015 в 03:10
  • 2
    Спасибо, очень грустно создавать поток, чтобы вернуться к теме UI, но только это решение спасло мое дело. – Pierre Maoui 4 May 2015 в 17:16
  • 3
    Важным аспектом является то, что wait(5000); не находится внутри Runnable, иначе ваш пользовательский интерфейс замерзнет в течение периода ожидания. Вы должны рассмотреть возможность использования AsyncTask вместо Thread для таких операций. – Martin 12 August 2015 в 07:44
  • 4
    Ты спас меня, мужик. Благодарю. – Pb Studies 27 April 2018 в 22:14
  • 5
    это так плохо для утечки памяти – Rafael Lima 6 May 2018 в 20:58

В моем случае звонящий звонит слишком много раз за короткое время, получит эту ошибку, я просто ставил проверенную проверку времени, чтобы ничего не делать, если слишком короткий, например. игнорировать, если функция вызывается менее 0,5 секунды:

    private long mLastClickTime = 0;

    public boolean foo() {
        if ( (SystemClock.elapsedRealtime() - mLastClickTime) < 500) {
            return false;
        }
        mLastClickTime = SystemClock.elapsedRealtime();

        //... do ui update
    }
0
ответ дан 林果皞 15 August 2018 в 21:54
поделиться
0
ответ дан Kaushal Sachan 29 October 2018 в 04:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: