#android #android-ui #android-gridview
#Android #android-gridview
Вопрос:
В настоящее время у меня есть GridView, и у каждого элемента должна быть отдельная ProgressBar. Элементы представляют отдельные загрузки, и я хотел бы показать состояние загрузок с помощью этих панелей прогресса.
Но как я должен их обновить? Моя проблема в том, что согласно документам (и тому, что я слышал в видеороликах Google IO), единственный способ обновить элементы в AdapterViews — это обновить назначенный адаптер и вызывать .notifyDataSetChanged() после каждого обновления.
Конечно, это действительно работает и в этом случае, но обновления происходят довольно часто (5-10 обновлений в секунду). И вызов .notifyDataSetChanged с такой частотой прерывает любое взаимодействие с GridView. Например. пользователь пытается долго нажимать на элемент в сетке, но событие нажатия останавливается, потому что .notifyDataSetChanged был вызван для обновления хода загрузки.
Есть ли какой-либо другой способ сделать это? Должен ли я отказаться от AdapterViews и использовать что-то другое?
Ответ №1:
Для ситуаций, подобных вашей, с частыми обновлениями (много раз в секунду) notifyDataSetChanged — неправильный способ — вам нужно обновлять отдельные представления напрямую.
Не видя вашего кода и взаимосвязи между загрузкой файла и записью в GridView, трудно точно сказать, какие вызовы вам понадобятся, но:
-В GridView есть «getChildAt», который вы можете использовать для получения представления по определенному индексу.
-Нет смысла обновлять представление, если оно даже не видно. Если это не находится между getFirstVisiblePosition() и getLastVisiblePosition(), игнорируйте это, оно будет отображаться с обновленными данными всякий раз, когда оно будет перерисовываться.
Комментарии:
1. Спасибо, я рассматривал возможность использования этой опции, но я не был уверен, как обрабатывать случаи, когда элемент, который необходимо обновить, в данный момент не отображается.
Ответ №2:
Я сделал это в одном проекте. Вы можете обновить пользовательский интерфейс, если используете Asysctask без .notifyDataSetChanged() . Например, у меня есть метод загрузки в моих утилит. класс
public static String downloadFile(DownloadItem downItem, AsynBackGroundFileLoader asynBackGroundFileLoader, String fileName,
String fileURL) {
// Spiking my code
while (bufferLength = inputStream.read(buffer) > 0 ) {
fileOutput.write(buffer, 0, bufferLength);
// add up the size so we know how much is downloaded
downloadedSize = bufferLength;
// this is where you would do something to report the progress,
int pro = ((int) (downloadedSize * 100 / totalSize));
asynBackGroundFileLoader.updateProgress(pro);
}
}
И в моей AsyncTask
public class AsynBackGroundFileLoader extends AsyncTask < Void , Integer , String > {
public AsynBackGroundFileLoader (DownloadItem dItem , TableLayout progressBarHodler , UpgradeActivity listener ) {
try {
mDownloadingProgressBarHolder = progressBarHodler ;
this.mDownloadingProgressBarHolder.setVisibility ( View.VISIBLE ) ;
mDownloadingProgressBar = ( ProgressBar ) mDownloadingProgressBarHolder.findViewById ( R.id.downloading_progress_bar ) ;
downloadCancelButton = ( ImageButton ) mDownloadingProgressBarHolder.findViewById ( R.id.downloading_progress_cancel_btn ) ;
downloadCancelButton.setImageResource ( R.drawable.btn_cancel );
@ Override
protected void onPreExecute ( ) {
}
@ Override
protected String doInBackground ( Void ... params ) {
boolean loadSuccess = Utils.downloadFile ( downItem , this , mFileName , downItem.getLink ( ) ) ;
return "" loadSuccess ;
}
@ Override
protected void onPostExecute ( String result ) {
}
public void updateProgress ( int progressPercentage ) {
try {
if ( progressPercentage < 0 ) {
progressPercentage = 0 ;
} else if ( progressPercentage > 100 ) {
progressPercentage = 100 ;
}
//Here I am updating my UI without making list to notifyDataChanged()
currentCompletedProgress = progressPercentage ;
// This is my progressbar in UI that update , I got this progressbar by passing UI item view in constructor
mDownloadingProgressBar.setProgress ( progressPercentage ) ;
downItem.setTotalProgress ( currentCompletedProgress ) ;
} catch ( Exception e ) {
Log.e ( TAG , "Exception = " e.toString ( ) ) ;
e.printStackTrace ( ) ;
}
}
public ProgressBar getmDownloadinProgressBar ( ) {
return mDownloadingProgressBar ;
}
}
Я начинаю загрузку, когда пользователь нажимает на строку списка
public void onItemClick(AdapterView<?> tempadapter, View view, int position, long arg3) {
TableLayout table = ((TableLayout) view.findViewById(R.id.downloading_progress_holder));
DownloadItem temp = adapter.items.get(position);
AsynBackGroundFileLoader bgdownloader = new AsynBackGroundFileLoader(temp, table, UpgradeActivity.this);
bgdownloader.execute();
}
table.setVisibility(View.VISIBLE);
}