【问题标题】:How to use AsyncTask with ListView Adapter如何将 AsyncTask 与 ListView 适配器一起使用
【发布时间】:2017-03-04 23:48:09
【问题描述】:

所以,我有一个ListView,我在我的TodayFragment 上显示它。有TodayTaskAdapter,可以定制这个列表。加载活动时,由于列表的原因,需要花费很多时间。并减慢应用程序的速度。问题是:

我应该如何正确使用 AsyncTask?以及使用它的正确位置:

  1. 在片段中,设置适配器时;
  2. getView()方法的适配器里面做操作 背景;
  3. 还是其他地方?

我还没有完全进入它。需要帮助。

TodayFragment

public class TodayFragment extends AbstractTabFragment
{
    public static final String TODAY_PAGE = "TODAY_PAGE";
    private static final int LAYOUT = R.layout.fragment_today;

    private ListView task_list;

    private TodayTaskAdapter today_task_adapter;

    private Event event;
    private Event event1;
    private Event event3;

    private Event event4;
    private Event event5;

    private Event event6;
    private Event event7;

    private Event event8;
    private Event event9;

    public static TodayFragment newInstance(int page, Context context)
    {
        Bundle args = new Bundle();
        args.putInt(TODAY_PAGE, page);

        TodayFragment fragment = new TodayFragment();
        fragment.setArguments(args);
        fragment.setContext(context);
        fragment.setTitle(context.getString(R.string.tab_today_name));

        return fragment;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        view = inflater.inflate(LAYOUT, container, false);

        task_list = (ListView) view.findViewById(R.id.tasks_list);

        today_task_adapter = new TodayTaskAdapter(getActivity(), R.layout.today_list_item);

        eventCreation();

        today_task_adapter.add(new EventTypeSection("Schedule"));
        today_task_adapter.add(event);
        today_task_adapter.add(event1);
        today_task_adapter.add(event3);

        today_task_adapter.add(new EventTypeSection("ToDo"));
        today_task_adapter.add(event4);
        today_task_adapter.add(event5);

        today_task_adapter.add(new EventTypeSection("Work Task"));
        today_task_adapter.add(event6);
        today_task_adapter.add(event7);

        today_task_adapter.add(new EventTypeSection("Birthday"));
        today_task_adapter.add(event8);
        today_task_adapter.add(event9);

        task_list.setAdapter(today_task_adapter);

        return view;
    }

    private void eventCreation()
    {
        event = new Schedule(1,"Algorythm Theory", ScheduleType.LESSON, "10:20 AM", "11:55 AM", "07.01.2017", EventType.SCHEDULE, "Waiting", 79);
        event1 = new Schedule(2,"Object-oriented programming", ScheduleType.LABORATORY_WORK, "12:00 AM", "01:30 PM", "07.01.2017", EventType.SCHEDULE, "Waiting", 63);
        event3 = new Schedule(2,"Aplied Math", ScheduleType.EXAM, "01:50 PM", "03:35 PM", "07.01.2017", EventType.SCHEDULE, "Waiting", 17);

        event4 = new ToDo(5,"Clean house", "09:30 AM", "03:35 PM", "07.01.2017", EventType.TODO, "Waiting", 91);
        event5 = new ToDo(7,"Buy grocery and other things", "01:30 AM", "02:25 PM", "07.01.2017", EventType.TODO, "Waiting", 23);

        event6 = new WorkTask(5,"Refactoring", "09:30 AM", "01:35 PM", "07.01.2017", EventType.WORKTASK, "Waiting", 81);
        event7 = new WorkTask(7,"Build database", "04:30 PM", "05:25 PM", "07.01.2017", EventType.WORKTASK, "Waiting", 33);

        event8 = new Birthday(8,"Taras's birthday", "09:30 AM", "01:35 PM", "07.01.2017", EventType.BIRTHDAY, "Waiting", 71, new Location(1, 2, "Roksolany", "Lviv", "Ukraine"));
        event9 = new Birthday(9,"John's birthday", "04:30 PM", "05:25 PM", "07.01.2017", EventType.BIRTHDAY, "Waiting", 53, new Location(1, 2, "Roksolany", "Lviv", "Ukraine"));
    }
}

TodayTaskAdapter

import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import com.example.twinkle94.dealwithit.R;
import com.example.twinkle94.dealwithit.events.Event;
import com.example.twinkle94.dealwithit.events.task_types.Schedule;
import com.example.twinkle94.dealwithit.events.type_enums.EventType;

import java.util.ArrayList;
import java.util.List;

public class TodayTaskAdapter extends ArrayAdapter
{
    private final String NAME = TodayTaskAdapter.class.getSimpleName();

    private static final int TYPE_HEADER = 0;
    private static final int TYPE_LIST = 1;

    private List<Item> list_of_tasks = new ArrayList<>();

    public TodayTaskAdapter(Context context, int resource)
    {
        super(context, resource);
    }

    public void add(Item event)
    {
        list_of_tasks.add(event);
    }

    @Override
    public int getCount()
    {
        return list_of_tasks.size();
    }

    @Nullable
    @Override
    public Item getItem(int position)
    {
        return list_of_tasks.get(position);
    }

    @Override
    public int getItemViewType(int position)
    {
        return getItem(position).getType() == EventType.NO_TYPE ?
                RowType.HEADER_ITEM.ordinal()
                :
                RowType.LIST_ITEM.ordinal();
    }

    @Override
    public int getViewTypeCount()
    {
        return RowType.values().length;
    }

    @NonNull
    @Override
    public View getView(int position, View convertView, @NonNull ViewGroup parent)
    {
        EventViewHolder eventViewHolder;

        // Get the data item type for this position
        int type = getItemViewType(position);

        if(convertView == null)
        {
            eventViewHolder = new EventViewHolder();

            // Inflate XML layout based on the type
            convertView = getInflatedLayoutForType(type, parent);

            switch (type)
            {
                case TYPE_HEADER:
                    initHeader(convertView, eventViewHolder);
                    break;

                case TYPE_LIST:
                    initViews(convertView, eventViewHolder);
                    break;
            }

            convertView.setTag(eventViewHolder);
        }

        else
        {
            eventViewHolder = (EventViewHolder) convertView.getTag();
        }

        //set all views with values from list
        setViewValues(position, eventViewHolder);

        return convertView;
    }

    private void setViewValues(int position, EventViewHolder eventViewHolder)
    {
        Item event = getItem(position);

        int type_color;
        String task_title;
        String from_time;
        String to_time;
        String importance;
        String interest;

        if (event != null)
        {
            switch (event.getType())
            {
                case SCHEDULE:
                    type_color = ContextCompat.getColor(getContext(), R.color.colorTypeSchedule);
                    task_title = ((Event)(event)).getTitle();
                    String schedule_type = ((Schedule)(event)).getScheduleType().toString();
                    int schedule_type_image = getSchedule_type_image(event);
                    from_time = ((Event)(event)).getTime_start();
                    to_time = ((Event)(event)).getTime_end();
                    importance = Integer.toString(((Event)(event)).getImportance()) + "%";
                    interest = Integer.toString(((Event)(event)).getImportance() + 9) + "%";

                    eventViewValues(eventViewHolder, type_color, task_title, schedule_type_image, schedule_type, from_time, to_time, importance, interest, View.VISIBLE, View.VISIBLE);
                    break;

                case TODO:
                    type_color = ContextCompat.getColor(getContext(), R.color.colorTypeToDo);
                    task_title = ((Event)(event)).getTitle();
                    from_time = ((Event)(event)).getTime_start();
                    to_time = ((Event)(event)).getTime_end();
                    importance = Integer.toString(((Event)(event)).getImportance()) + "%";
                    interest = Integer.toString(((Event)(event)).getImportance() + 9) + "%";

                    eventViewValues(eventViewHolder, type_color, task_title, 0, "", from_time, to_time, importance, interest, View.GONE, View.GONE);
                    break;

                case WORKTASK:
                    type_color = ContextCompat.getColor(getContext(), R.color.colorTypeWorkTasks);
                    task_title = ((Event)(event)).getTitle();
                    from_time = ((Event)(event)).getTime_start();
                    to_time = ((Event)(event)).getTime_end();
                    importance = Integer.toString(((Event)(event)).getImportance()) + "%";
                    interest = Integer.toString(((Event)(event)).getImportance() + 9) + "%";

                    eventViewValues(eventViewHolder, type_color, task_title, 0, "", from_time, to_time, importance, interest, View.GONE, View.GONE);
                    break;

                case BIRTHDAY:
                    type_color = ContextCompat.getColor(getContext(), R.color.colorTypeBirthday);
                    task_title = ((Event)(event)).getTitle();
                    from_time = ((Event)(event)).getTime_start();
                    to_time = ((Event)(event)).getTime_end();
                    importance = Integer.toString(((Event)(event)).getImportance()) + "%";
                    interest = Integer.toString(((Event)(event)).getImportance() + 9) + "%";

                    eventViewValues(eventViewHolder, type_color, task_title, 0, "", from_time, to_time, importance, interest, View.GONE, View.GONE);
                    break;

                case NO_TYPE:
                    String type = ((EventTypeSection) getItem(position)).getTitle();

                    eventViewHolder.headerText.setText(type);

                    switch(type)
                    {
                        case "Schedule":
                            eventViewHolder.headerText.setBackgroundColor(ContextCompat.getColor(getContext(), R.color.colorTypeSchedule));
                            break;

                        case "ToDo":
                            eventViewHolder.headerText.setBackgroundColor(ContextCompat.getColor(getContext(), R.color.colorTypeToDo));
                            break;

                        case "Work Task":
                            eventViewHolder.headerText.setBackgroundColor(ContextCompat.getColor(getContext(), R.color.colorTypeWorkTasks));
                            break;

                        case "Birthday":
                            eventViewHolder.headerText.setBackgroundColor(ContextCompat.getColor(getContext(), R.color.colorTypeBirthday));
                            break;

                    }

                    break;

                //TODO: add default, when task have no type.
            }
        }
    }

    private int getSchedule_type_image(Item event)
    {
        int schedule_type_image = R.drawable.ic_lesson_type;

        switch(((Schedule)(event)).getScheduleType())
        {
            case LESSON:
                schedule_type_image = R.drawable.ic_lesson_type;
                break;

            case EXAM:
                schedule_type_image = R.drawable.ic_exam_schedule_type;
                break;

            case LABORATORY_WORK:
                schedule_type_image = R.drawable.ic_lab_work_schedule_type;
                break;
        }
        return schedule_type_image;
    }

    //TODO: overload method with less parameters for different types of tasks.
    private void eventViewValues(EventViewHolder eventViewHolder, int type_color, String task_title, int scheduleTypeImage, String schedule_type,
                                 String from_time, String to_time, String importance, String interest,
                                 int task_type_visibility, int task_type_image_visibility)
    {
        eventViewHolder.type_color.setBackgroundColor(type_color);

        eventViewHolder.task_title.setText(task_title);
        eventViewHolder.task_type.setText(schedule_type);
        eventViewHolder.task_type_image.setImageResource(scheduleTypeImage);

        eventViewHolder.task_type.setVisibility(task_type_visibility);
        eventViewHolder.task_type_image.setVisibility(task_type_image_visibility);

        eventViewHolder.from_title.setText("From");
        eventViewHolder.from_time.setText(from_time);
        eventViewHolder.from_image.setImageResource(R.drawable.ic_from_time);

        eventViewHolder.to_title.setText("To");
        eventViewHolder.to_time.setText(to_time);
        eventViewHolder.to_image.setImageResource(R.drawable.ic_to_time);

        eventViewHolder.importance.setText(importance);
        eventViewHolder.importance_image.setImageResource(R.drawable.ic_importance_icon);

        eventViewHolder.interest.setText(interest);
        eventViewHolder.interest_image.setImageResource(R.drawable.ic_interest_today_page);
    }

    private View getInflatedLayoutForType(int type, ViewGroup parent)
    {
        LayoutInflater layoutInflater = (LayoutInflater) this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View inflated_view = null;

        switch(type)
        {
            case TYPE_HEADER:
                inflated_view = layoutInflater.inflate(R.layout.today_list_header, parent, false);
                break;

            case TYPE_LIST:
                inflated_view = layoutInflater.inflate(R.layout.today_list_item, parent, false);
                break;
        }

        return inflated_view;
    }

    private void initHeader(View row, EventViewHolder eventViewHolder)
    {
        eventViewHolder.headerText = (TextView) row.findViewById(R.id.tasks_title);
    }

    private void initViews(View row, EventViewHolder eventViewHolder)
    {
        eventViewHolder.type_color = row.findViewById(R.id.type_color);

        eventViewHolder.task_title = (TextView) row.findViewById(R.id.task_title);
        eventViewHolder.task_type = (TextView) row.findViewById(R.id.task_type);
        eventViewHolder.task_type_image = (ImageView) row.findViewById(R.id.lesson_type);

        eventViewHolder.from_title = (TextView) row.findViewById(R.id.from_title);
        eventViewHolder.from_time = (TextView) row.findViewById(R.id.from_time);
        eventViewHolder.from_image = (ImageView) row.findViewById(R.id.from_time_icon);

        eventViewHolder.to_title = (TextView) row.findViewById(R.id.to_title);
        eventViewHolder.to_time = (TextView) row.findViewById(R.id.to_time);
        eventViewHolder.to_image = (ImageView) row.findViewById(R.id.to_time_icon);

        eventViewHolder.importance = (TextView) row.findViewById(R.id.importance_percent);
        eventViewHolder.importance_image = (ImageView) row.findViewById(R.id.importance_icon);

        eventViewHolder.interest = (TextView) row.findViewById(R.id.interest_percent);
        eventViewHolder.interest_image = (ImageView) row.findViewById(R.id.interest_icon);
    }

    private static class EventViewHolder
    {
        View type_color;

        TextView task_title;
        TextView task_type;
        ImageView task_type_image;

        TextView from_title;
        TextView from_time;
        ImageView from_image;

        TextView to_title;
        TextView to_time;
        ImageView to_image;

        TextView importance;
        ImageView importance_image;

        TextView interest;
        ImageView interest_image;

        //Header text
        TextView headerText;
    }

    private enum RowType
    {
        HEADER_ITEM, LIST_ITEM
    }
}

【问题讨论】:

  • When the actvity is loading, it takes a lot of time because of the list. - 我认为您需要质疑为什么您的列表需要很长时间才能填充,而不是假设它需要是异步的。关于异步任务 - 您不能从主 ui 以外的任何其他线程执行任何视图操作(即textView.setText("some text");)。
  • 哦,谢谢。但我在文档中看到:public void onClick(View v) { new Thread(new Runnable() { public void run() { // a potentially time consuming task final Bitmap bitmap = processBitMap("image.png"); mImageView.post(new Runnable() { public void run() { mImageView.setImageBitmap(bitmap); } }); } }).start(); } 这不是异步任务,但仍然是另一个线程,它使用 UI 元素而不是通知主线程有关更改。
  • 评论示例中的mImageView.post() 代码将ImageView 的操作重新置于UI 线程上。您还在寻找问题的答案吗?
  • @Cheticamp,是的,我还在寻找。如果你有,请分享)

标签: android listview android-asynctask android-adapter getview


【解决方案1】:

由于各种原因,列表可能需要很长时间才能加载:数据量大、与后端服务器的连接速度慢、计算需求高等。这些耗时的任务通常只需要一些时间,而且什么都没有除了尽量减少对用户的影响之外,我们可以做的。

使用AsyncTaskLoader 等进行后台处理的目标是完成一项耗时的任务并将其移出运行用户界面的线程(UI 线程)并尽可能多地重叠处理尽可能使应用程序不会出现“挂起”。所以,尽快启动AsyncTask。根据您的应用程序,处理可能会在用户需要查看结果数据时完成,这将是很棒的。如果没有,那么您可能需要发送ProgressBar 让他们知道他们需要稍等片刻。 AsyncTaskonPreExecute()onProgressUpdate()onPostExecute() 方法将帮助您与用户(在 UI 线程上)就您的应用程序在获取数据方面取得的进展进行沟通。请参阅documentation

还可以查看this example。在设置ListView 适配器后立即调用AsyncTask。这是执行此操作的常见位置。那将在您的片段中。 (getView() 位置不对。)

public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

adpt = new SimpleAdapter(new ArrayList(), this);
ListView lView = (ListView) findViewById(R.id.listview);

lView.setAdapter(adpt);

// Exec async load task
(new AsyncListViewLoader()).execute("http://10.0.2.2:8080/JSONServer/rest/ContactWS/get");
}

如果您有很多数据要显示,那么您可能需要实现一些逻辑来进行无休止的滚动,在其中显示一两页数据,然后再获取更多数据。只需搜索“listView 无限滚动”以获取更多信息。

我希望这会有所帮助。

【讨论】:

  • 感谢您的回答,但我想再问一件事。我已经为列表制作了像 link 这样的 AsyncTask。好吗?并在片段中调用:link。但是是一个问题。有时应用程序崩溃。因为它看不到上下文。
  • 一切看起来都不错。你在哪里存储contextonActivityCreated() 看不到它?看不到它还是 null 还是抛出了其他异常?
  • 哦,抱歉,这种方法效果很好,但从onCreateView() fragment 它给了我NullPointerException。但是,我认为它没有看到列表,但不知道为什么(error
  • 从您的onCreateView() 代码中不清楚context 的来源。它是类成员变量吗?它一定要是。确保将其设置为片段的Activity。您无法捕捉到正确的上下文或任何上下文。 setContext() 是什么?我会检查一下,以确保它正在做你想做的事。上下文可能是棘手的事情。幸运的是,有很多关于 Stack Overflow 的指导。
  • 是的,它是来自AbstractFragment absFrag 的班级成员。这是我给片段contextContext。我列出的这种背景。 initList.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-12
  • 1970-01-01
  • 1970-01-01
  • 2017-08-19
  • 2017-11-17
  • 2012-03-18
相关资源
最近更新 更多