==
выполняет контрольную проверку равенства, ссылаясь на то, что 2 объекта (строки в этом случае) относятся к одному и тому же объекту в памяти.
Метод equals()
будет проверять, будет ли содержимое или состояния двух объектов одинаковы.
Очевидно, что ==
работает быстрее, но во многих случаях может (может) давать ложные результаты, если вы просто хотите сказать, имеет ли 2 String
s тот же текст.
Определенно рекомендуется использовать метод equals()
.
Не беспокойтесь о производительности. Некоторые способы поощрения использования String.equals()
:
String.equals()
сначала проверяет ссылочное равенство (используя ==
), и если две строки одинаковы по ссылке, дальнейший расчет Выполняется! String.equals()
будет проверять длину строк. Это также является быстрой операцией, поскольку класс String
хранит длину строки, не нужно считать символы или кодовые точки. Если длины отличаются, дальнейшая проверка не выполняется, мы знаем, что они не могут быть равными. Когда все сказано и даже если у нас есть гарантия, что строки являются стажерами, использование метода equals()
все еще не является издержками, которые можно было бы подумать, определенно рекомендуемым способом. Если вам нужна эффективная проверка ссылок, используйте перечисления, где гарантируется спецификацией и реализацией языка, что одно и то же значение перечисления будет одним и тем же объектом (по ссылке).
Используйте этот код, и нет необходимости в функции 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();
}
Это трассировка стека упомянутого исключения
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()
, когда мы раздуваем макет и позже, когда вы получаете исключение.
Для меня проблема заключалась в том, что я явно вызывал onProgressUpdate()
из моего кода. Это не должно быть сделано. Вместо этого я вызвал publishProgress()
и решил эту ошибку.
Вы можете использовать Handler для удаления View, не нарушая основной поток пользовательского интерфейса. Вот пример кода
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
//do stuff like remove view etc
adapter.remove(selecteditem);
}
});
Я вижу, что вы приняли ответ @ 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);
При использовании AsyncTask Обновление пользовательского интерфейса в методе onPostExecute
@Override
protected void onPostExecute(String s) {
// Update UI here
}
Обычно любое действие, связанное с пользовательским интерфейсом, должно выполняться в основном потоке или потоке пользовательского интерфейса, то есть в том, что выполняется onCreate()
и обработка событий. Один из способов убедиться в этом: runOnUiThread () , другой - обработчики.
ProgressBar.setProgress()
имеет механизм, для которого он всегда будет выполняться в основном потоке, поэтому поэтому он работал.
См. Нержавеющая резьба .
Я был в этой ситуации, но нашел решение с объектом 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 со вторым потоком».
В моем случае у меня есть EditText
в Adapter, и он уже находится в потоке пользовательского интерфейса. Однако, когда эта активность загружается, она вылетает с этой ошибкой.
Мое решение: мне нужно удалить <requestFocus />
из EditText в XML.
error.setText(res.toString());
внутри метода run (), но я не мог использовать res, потому что он не был окончательным .. слишком плохо
– noloman
1 August 2011 в 13:31
myActivityObject.runOnUiThread(etc)
– Kirby
17 February 2012 в 23:27
runOnUiThread()
- метод Деятельности. Я использовал код в фрагменте. Я закончил делать getActivity().runOnUiThread(etc)
, и это сработало. Фантастика!;
– lejonl
19 August 2013 в 21:07
runOnUiThread
на runTestOnUiThread
. благодаря
– DaddyMoe
21 February 2016 в 18:45
Я решил это, поставив 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();
wait(5000);
не находится внутри Runnable, иначе ваш пользовательский интерфейс замерзнет в течение периода ожидания. Вы должны рассмотреть возможность использования AsyncTask
вместо Thread для таких операций.
– Martin
12 August 2015 в 07:44
В моем случае звонящий звонит слишком много раз за короткое время, получит эту ошибку, я просто ставил проверенную проверку времени, чтобы ничего не делать, если слишком короткий, например. игнорировать, если функция вызывается менее 0,5 секунды:
private long mLastClickTime = 0;
public boolean foo() {
if ( (SystemClock.elapsedRealtime() - mLastClickTime) < 500) {
return false;
}
mLastClickTime = SystemClock.elapsedRealtime();
//... do ui update
}