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

Другие вопросы по тегам