понедельник, 19 декабря 2011 г.

Make part of layout invisible and the other part visible


I would like to make a LinearLayout that was created from xml invisible, and another LinearLayout visible to replace it. The replacement layout starts out as invisible. When I make the originally visible layout invisible, it still leaves space for it on the screen. How can I refresh the screen so that space is gone?
link|improve this question

79% accept rate
feedback
Perhaps you are mixing up View.INVISIBLE with View.GONE:
int GONE This view is invisible, and it doesn't take any space for layout purposes.
int INVISIBLE This view is invisible, but it still takes up space for layout purposes.

вторник, 13 декабря 2011 г.

Потоки Андроид


Справочник по android API

Потоки

В андроиде добавлены дополнительные возможности для работы с потоками.

Класс Handler

Когда объект Handler создается, он назначается текущему потоку и его очереди сообщений. После этого он может доставлять сообщения и код (Runnable) в очередь сообщений для обработки и выполнения их в будущем. Таким образом, объект используется для одновременной обработки сообщений и выполнения некоторого кода или для выполнения кода в другом потоке. Ниже приведены некоторые методы класса:
  • dispatchMessage(Message msg) - обработчик системных сообщений
  • dump(Printer pw, String prefix) - дамп
  • handleMessage(Message msg) - обработчик входящих сообщений, должен переопределятся потомками
  • hasMessages(int what, Object object) - проверяет есть ли не обработанное сообщение с кодом 'what' и объектом сообщения 'object'
  • hasMessages(int what) - проверяет есть ли не обработанное сообщение с кодом 'what'
  • Message obtainMessage() - новое сообщение из глобального пула сообщений, есть вариации метода
  • boolean post(Runnable r) - послать r в очередь сообщений (т.е. выполнить код в потоке, в котором объект Handle был создан)
  • void removeCallbacks(Runnable r) - удалить все посланные r из очереди сообщений
  • void removeMessages(int what) - удалить сообщение с кодом 'what' из очереди
  • boolean sendMessage(Message msg) - поместить сообщение в конец очереди сообщений

метод runOnUiThread

Метод runOnUiThread класса Activity позволяет выполнить указанный код в UI потоке. Если текущий поток - UI поток, то он выполняется сразу, иначе помещается в очередь событий UI потока.
Обычно используется, когда нужно изменить элементы управления после выполнения какой-то задачи в другом потоке.

// снипет подгрузки изображения из интернета и установки его в виджет ImageView
(new Thread(new Runnable() {

 @Override
 public void run() {
   try {
   final Bitmap bm = ImageTool.loadBitmap(urlImg);
   CompanyView.this.runOnUiThread(new Runnable() {
                                    
      @Override
      public void run() {
         ico.setImageBitmap(bm);                                        
         }
      });
                                
   } catch (Exception e) {
        e.printStackTrace();
        }
   }
   })).start();

Класс AsyncTask

Класс AsyncTask облегчает выполнения задачи в отдельном потоке, с последующем отображением результата в потоке пользовательского интерфейса (UI).
Шаблон класса использует три типа
  • Params - тип параметров посылаемых перед запуском задачи;
  • Progress - тип, используемый для отображения прогресса операции;
  • Result - тип результата задачи;
Ниже приведены некоторые методы класса:
  • onPreExecute() - вызывается в потоке UI сразу после запуска задачи, на данном этапе обычно настраивают задачу, например, показывая индикатор прогресса в UI;
  • doInBackground(Params...) - запускается в отдельном потоке после завершения onPreExecute(). На этом этапе вычисляется результат, который передается методу onPostExecute;
  • Также на этом этапе могут использоваться вызовы publishProgress() для отображения текущего прогресса выполнения задачи;
  • onProgressUpdate(Progress...) - вызывается в потоке UI сразу после вызова publishProgress(). Метод используется для отображения прогресса в пользовательском интерфейсе;
  • onPostExecute(Result) - вызывается в потоке UI после завершения задачи;
  • execute(Params... params) - выполняет задачу с указанными параметрами;
  • isCancelled() - true, если задача была прервана;
  • cancel(boolean mayInterruptIfRunning) - попытка прервать задачу;

// пример из документации - загрузка файлов
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
     protected Long doInBackground(URL... urls) {
         int count = urls.length;
         long totalSize = 0;
         for (int i = 0; i < count; i++) {
             totalSize += Downloader.downloadFile(urls[i]);
             publishProgress((int) ((i / (float) count) * 100));
         }
         return totalSize;
     }

     protected void onProgressUpdate(Integer... progress) {
         setProgressPercent(progress[0]);
     }

     protected void onPostExecute(Long result) {
         showDialog("Downloaded " + result + " bytes");
     }
 }
 
 ...
 
 new DownloadFilesTask().execute(url1, url2, url3);
Задача должна запускаться из главного потока пользовательского интерфейса, иначе система выдаст ошибкуjava.lang.ExceptionInInitializerError.
Задачу можно запускать только один раз.

// При повторном запуске задачи система выдаст ошибку
//  Cannot execute task: the task has already been executed 
//  (a task can be executed only once)
at = new DownloadFilesTask();
at.execute(url1, url2, url3);
...
at.execute(url1, url2, url3);

// правильно
at = new DownloadFilesTask();
at.execute(url1, url2, url3);
...
at = new DownloadFilesTask();
at.execute(url1, url2, url3);

метод View.post

Если пытаться получить высоту TextView после изменения содержимого, результат скорей всего будет неверным.
В этом случае высота запрашивается через метод post класса View. Указанная задача будет добавлена в очередь сообщений и выполнена в потоке UI.

TextView tvDescription;
...
tvDescription.setText("example for darkraha.com"));
tvDescription.post(new Runnable() {

       @Override
       public void run() {
           if(tvDescription.getMeasuredHeight() > getCollapsedHeight()){            
              evDescription.setCollapse();
           }
         }
});