AsyncTask с ListView с двумя макетами строк
У меня есть просмотр списка с 2 различными типами строк (как в этом вопросе). Работает нормально, но очень медленно при прокрутке. Поэтому я прочитал, что для борьбы с этим нужно использовать AsyncTask. Как я могу реализовать это, когда используются два разных типа строк?
Я попытался использовать две разные AsyncTasks (раздувая строку в doInBackground), но я получаю всевозможные ошибки:
в getView():
if (convertView == null) {
switch (type) {
case TYPE_DAY:
new ForecastDayTask(position, forecastHolder, convertView,
forecastHolder, mInflater, forecastdata).execute();
break;
case TYPE_DATA:
new ForecastTask(position, forecastHolder, convertView,
forecastHolder, mInflater, forecastdata).execute();
break;
}
Я также попытался использовать тот же класс AsyncTask и передать те же данные И TYPE_DAY/TYPE_DATA, но это ужасно сложно, и я получаю NullPointerExceptions.
Есть идеи? Заранее спасибо!
1 ответ
Я решил это так:
- Я расширил BaseAdapter, у которого есть список всех возможных ListItems.
- getView использует ViewHolderPattern для повторного использования представлений
- ширина представления зависит от HolderItem, соответственно. в нужное время (это горизонтальный список, показывающий трансляции с различной продолжительностью)
- GetView запускает AsyncTask, который занимает два Holder, ViewHolder и DataHolder
- AsyncTask необходим для запуска onPostExecute Thread, который выполняет GUIStuff, DrawRunnable
- В DrawRunnable я решаю, как покрасить фон, и что должно быть представлено пользователю в зависимости от продолжительности трансляции.
Мне нравится ваш способ запуска двух разных задач в зависимости от типа. в моем случае это были бы разные типы продолжительности. Поэтому я должен решить при создании DrawBroadcastRunnable в onPostExecute, какой DrawXTypeRunnable должен начать. Я пометил позицию в коде с помощью (XTYPE)
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewBroadcastItemHolder viewItemHolder;
if (convertView == null) {
convertView = (RelativeLayout) layoutInflater.inflate(layoutId,
parent, false);
viewItemHolder = new ViewBroadcastItemHolder();
viewItemHolder.logo = (ImageView) convertView
.findViewById(R.id.broadcast_guide_image);
viewItemHolder.time = (TextView) convertView
.findViewById(R.id.broadcast_guide_time);
viewItemHolder.title = (TextView) convertView
.findViewById(R.id.broadcast_guide_title);
viewItemHolder.divider = convertView
.findViewById(R.id.broadcast_guide_divider);
viewItemHolder.layout = (LinearLayout) convertView
.findViewById(R.id.broadcast_guide_item_linear_layout);
convertView.setTag(viewItemHolder);
} else {
viewItemHolder = (ViewBroadcastItemHolder) convertView.getTag();
convertView.setVisibility(View.GONE);
}
BroadcastHolder broadcastItem = getItem(position);
viewItemHolder.layout.getLayoutParams().width = broadcastItem.width;
BroadcastHolderAsyncArgument holder = new BroadcastHolderAsyncArgument(
convertView, viewItemHolder, broadcastItem, position);
holder.bcViewHolder.logo
.setImageBitmap(controller.getLogoPlaceholder());
BroadcastHolderAsyncArgument[] argument = { holder };
new AsyncTask<BroadcastHolderAsyncArgument, Void, BroadcastHolderAsyncArgument>() {
@Override
protected BroadcastHolderAsyncArgument doInBackground(
BroadcastHolderAsyncArgument... bcHolderArg) {
return bcHolderArg[0];
}
@Override
protected void onPostExecute(
BroadcastHolderAsyncArgument bcHolderArg) {
// Where to put in the decision which Strategy has to get done
//if(XTYPE){ new DrawBroadcast30ViewRunnable(..).run()}
//else if(YTYPE){new DrawBroadcast200ViewRunnable(..).run()}
//else if(ZTYPE){new DrawBroadcast10ViewRunnable(..).run()}
//else{new DrawBroadcast5ViewRunnable(..).run()}
new DrawBroadcastViewRunnable(bcHolderArg, position).run();
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, argument);
return convertView;
}
public class DrawBroadcastViewRunnable implements Runnable {
private BroadcastHolderAsyncArgument bcAsyncArgumentHolder;
private int position;
public DrawBroadcastViewRunnable(
BroadcastHolderAsyncArgument bcHolderArgument, int position) {
super();
this.bcAsyncArgumentHolder = bcHolderArgument;
this.position = position;
}
public void run() {
if (bcAsyncArgumentHolder.position == position) {
// Set Background Color of CatchUp, Live and Upcomming
if (Helper.isLiveBroadcast(
bcAsyncArgumentHolder.bcItemHolder.start,
bcAsyncArgumentHolder.bcItemHolder.stop)) {
bcAsyncArgumentHolder.bcViewHolder.isCatchup = false;
bcAsyncArgumentHolder.convertView
.setBackgroundColor(context.getResources()
.getColor(R.color.guide_live_broadcast));
} else if (bcAsyncArgumentHolder.bcViewHolder.isCatchup = Helper
.isCatchupBroadcast(
bcAsyncArgumentHolder.bcItemHolder.start,
bcAsyncArgumentHolder.bcItemHolder.stop)) {
bcAsyncArgumentHolder.convertView
.setBackgroundColor(context.getResources()
.getColor(R.color.guide_replay_broadcast));
} else {
// Upcoming Broadcast
bcAsyncArgumentHolder.convertView
.setBackgroundColor(context.getResources()
.getColor(R.color.guide_upcoming_broadcast));
bcAsyncArgumentHolder.bcViewHolder.isCatchup = false;
}
// very large layout, more than 30min
if (bcAsyncArgumentHolder.bcItemHolder.width >= 20 * controller
.getPixelPerMinute()) {
bcAsyncArgumentHolder.bcViewHolder.logo
.setVisibility(View.VISIBLE);
ImageLoader.getInstance().displayImage(
bcAsyncArgumentHolder.bcItemHolder.imageUrl,
bcAsyncArgumentHolder.bcViewHolder.logo);
bcAsyncArgumentHolder.bcViewHolder.title
.setVisibility(View.VISIBLE);
bcAsyncArgumentHolder.bcViewHolder.time
.setVisibility(View.VISIBLE);
bcAsyncArgumentHolder.bcViewHolder.title
.setText(bcAsyncArgumentHolder.bcItemHolder.title);
bcAsyncArgumentHolder.bcViewHolder.time.setText(Helper
.formatBroadcastTime(
bcAsyncArgumentHolder.bcItemHolder.start,
bcAsyncArgumentHolder.bcItemHolder.stop));
}
// medium layout, between 20 to 15min
if (bcAsyncArgumentHolder.bcItemHolder.width < 20 * controller
.getPixelPerMinute()
&& bcAsyncArgumentHolder.bcItemHolder.width > 15 * controller
.getPixelPerMinute()) {
ImageLoader.getInstance().displayImage(
bcAsyncArgumentHolder.bcItemHolder.imageUrl,
bcAsyncArgumentHolder.bcViewHolder.logo);
bcAsyncArgumentHolder.bcViewHolder.logo
.setVisibility(View.VISIBLE);
bcAsyncArgumentHolder.bcViewHolder.time
.setVisibility(View.VISIBLE);
bcAsyncArgumentHolder.bcViewHolder.title
.setVisibility(View.VISIBLE);
bcAsyncArgumentHolder.bcViewHolder.title
.setText(bcAsyncArgumentHolder.bcItemHolder.title);
bcAsyncArgumentHolder.bcViewHolder.time.setText(Helper
.formatBroadcastTime(
bcAsyncArgumentHolder.bcItemHolder.start,
bcAsyncArgumentHolder.bcItemHolder.stop));
}
// medium layout, between 15 to 5min
if (bcAsyncArgumentHolder.bcItemHolder.width <= 15 * controller
.getPixelPerMinute()
&& bcAsyncArgumentHolder.bcItemHolder.width > 5 * controller
.getPixelPerMinute()) {
bcAsyncArgumentHolder.bcViewHolder.logo
.setVisibility(View.GONE);
bcAsyncArgumentHolder.bcViewHolder.time
.setVisibility(View.GONE);
bcAsyncArgumentHolder.bcViewHolder.title
.setVisibility(View.VISIBLE);
bcAsyncArgumentHolder.bcViewHolder.title
.setText(bcAsyncArgumentHolder.bcItemHolder.title);
}
// smal layout, to 5min
if (bcAsyncArgumentHolder.bcItemHolder.width <= 5 * controller
.getPixelPerMinute()) {
bcAsyncArgumentHolder.bcViewHolder.logo
.setVisibility(View.GONE);
bcAsyncArgumentHolder.bcViewHolder.time
.setVisibility(View.GONE);
bcAsyncArgumentHolder.bcViewHolder.title
.setVisibility(View.GONE);
}
if (bcAsyncArgumentHolder.bcItemHolder.dummy) {
bcAsyncArgumentHolder.bcViewHolder.divider
.setVisibility(View.GONE);
} else {
bcAsyncArgumentHolder.bcViewHolder.divider
.setVisibility(View.VISIBLE);
}
if (!bcAsyncArgumentHolder.bcItemHolder.id.equalsIgnoreCase("")) {
bcAsyncArgumentHolder.bcViewHolder.broadcastId = Long
.parseLong(bcAsyncArgumentHolder.bcItemHolder.id);
}
bcAsyncArgumentHolder.convertView.setVisibility(View.VISIBLE);
}
}
Так как ты решил твою проблему? у моего решения осталась проблема, viewRecycling вызывает смешивание представлений, вызывая рендеринг 5-минутного макета вместо 40-минутного макета, потому что есть некоторый параллелизм при быстрой прокрутке. Я знаю, почему это так, но я не знаю, как это исправить, пока:-D