2013-04-16 3 views
1

У меня есть ImageButton, который выполняет длительную операцию при нажатии. Так что я безуспешно пытаюсь сделать это изменить изображение в начале onClick позвонить и изменить его в конце.Изменение изображения ImageButton при вызове onClick

Я пробовал приведенный ниже код, но то, что я нашел, является андроидом, перерисовывает изображение кнопки после того, как onClick закончен, поэтому он бесполезен.

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

Ниже приведен код, который я использую. Thread.sleep представляет собой длительную операцию. Я хотел бы, чтобы изображение изменилось, когда выполнение достигнет сна не после завершения onClick.

btnTest = (ImageButton) findViewById(R.id.btnTest); 
btnTest.setOnClickListener(new OnClickListener() { 
@Override 
public void onClick(View v) { 
    System.out.println("start"); 
    btnTest.setImageResource(R.drawable.add); 
    try { 
     Thread.sleep(1000); 
    } catch (InterruptedException e) { 
    } 

    System.out.println("end"); 
    btnTest.setImageResource(R.drawable.del); 
} 
}); 
+0

так что это вы хотели ?? Измените «ImageButton» bg, когда пользователь нажимает кнопку и возвращает ее, когда он отпускает сенсорный экран? – Renjith

+0

вы можете реализовать на сенсорном прослушивателе нажатие клавиши (кнопка нажата пользователем) и клавиша вверх (кнопка с пользователем) –

ответ

6

Ваша проблема в том, что вы sleep() на (или в противном случае блок) в потоке пользовательского интерфейса. Пожалуйста, поймите, что основной/пользовательский поток отвечает за перерисовку и обработку всех событий. Если вы сон там (onClick() исполняется ионный поток пользовательского интерфейса), тогда Android не сможет сделать что-нибудь связанный с ним интерфейс пользователя.

Основой является то, что многопоточный графический интерфейс был бы крайне неэффективным. Большинство вызовов, связанных с пользовательским интерфейсом, таких как setBackground, просто устанавливают некоторые данные или даже планируют некоторые другие действия, не имеют немедленного эффекта и будут давать результаты только в том случае, если элемент управления возвращается в основной контур управления потоком пользовательского интерфейса, например. для скоординированного перерисовки. Представьте себе, что произойдет, если вы запустите пару изменений макета один за другим, и каждый из них будет обработан немедленно - это приведет к огромному количеству вычислений, которые в следующий момент станут недействительными.

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

Что вам нужно сделать, так это выполнить долговременную работу на AsyncTask или Thread. Для начала, я бы попробовал AsyncTask. В методе onPostExecute() AsyncTask, который снова запускается в потоке пользовательского интерфейса, вы можете управлять своим пользовательским интерфейсом по своему усмотрению.

Для быстрого успеха, вы можете также использовать тему:

@Override 
public void onClick(View v) { 
    // on UI thread 
    btnTest.setImageResource(R.drawable.add); 
    // launch concurrent thread 
    (new Thread(new Runnable() { 
      @Override 
      // the code of this method will run concurrently 
      public void run() { 
       System.out.println("start"); 
       try { 
        Thread.sleep(1000); 
       } catch (InterruptedException e) {} 
       System.out.println("end"); 
       // at this point, we need to get back to the UI thread 
       // for simplicity, we use the view's convenience method for that 
       v.post(new Runnable() { 
        @Override 
        // the code of this method will run on the UI thread 
        public void run() { 
         btnTest.setImageResource(R.drawable.del); 
        } 
       }) 
      } 
     }) 
    ).start(); 
} 

AsyncTask выглядит гораздо лучше, но это не так легко создавать и использовать на лету.

Обратите внимание, что код, указанный выше, создает Thread, который будет работать до тех пор, пока он не покинет свой метод run(), или Android не уничтожит процесс Linux, на котором размещено ваше приложение.

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

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

Кроме того, вы упомянули, что вы выполняете долговременную операцию. Вопрос в том, делает ли это операцию wait или делает это вычислить что-то. Если он что-то вычисляет, вы можете обнаружить, что он теперь занимает десять раз дольше, если вы не adjust the AsyncTask/Thread priority as described here.

+0

Спасибо, хорошо объяснено и полезно –

+0

Это блестящий ответ, спасибо большое –

+0

@JohnBale Спасибо. Рад, что ты нашел это полезным! –

1

Я надеюсь, что вы будете выполнять некоторую операцию в onclick, а не только Thread.Sleep().

В этом случае вы можете использовать следующий подход, используя AsyncTask.

btnTest = (ImageButton) findViewById(R.id.btnTest); 
btnTest.setOnClickListener(new OnClickListener() { 

    @Override 
    public void onClick(View v) { 

     new SomeLongRunningOperationAsyncTask().execute(); 

    } 
}); 

класс AsyncTask для длительного запущенного процесса.

class SomeLongRunningOperationAsyncTask extends AsyncTask<Void, Void, Void> 
{ 

    @Override 
    protected void onPreExecute() { 

     super.onPreExecute(); 
     System.out.println("start"); 
     btnTest.setImageResource(R.drawable.add); 

    } 

    @Override 
    protected Void doInBackground(Void... params) { 

     //your long running operation. 
     return null; 
    } 

    @Override 
    protected void onPostExecute(Void result) { 

     super.onPostExecute(result); 
     System.out.println("end"); 
     btnTest.setImageResource(R.drawable.del); 
    } 
} 
Смежные вопросы