【问题标题】:CustomListView Crashes When Scrolling Fast快速滚动时 CustomListView 崩溃
【发布时间】:2014-06-29 23:49:43
【问题描述】:

我正在尝试实现自定义列表视图。它显示得很好,当我慢慢滚动它时,它可以正常工作。但是,当我开始更快地滚动时,应用程序崩溃了。下面是我的列表视图适配器代码。

import java.util.List;

import MainActivity.ListViewItem;

import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

public class CustomListViewAdapter extends BaseAdapter {

LayoutInflater inflater;
List<ListViewItem> items;

public CustomListViewAdapter(Activity context, List<ListViewItem> items) {
    super();

    this.items = items;
    this.inflater = (LayoutInflater) context
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

@Override
public int getCount() {
    // TODO Auto-generated method stub
    return items.size();
}

@Override
public Object getItem(int position) {
    // TODO Auto-generated method stub
    return null;
}

@Override
public long getItemId(int position) {
    // TODO Auto-generated method stub
    return 0;
}

@Override
public View getView(final int position, View convertView, ViewGroup parent) {
    // TODO Auto-generated method stub

    ListViewItem item = items.get(position);

    View vi = convertView;

    if (item.Type.equals("Homework")) {

        if (convertView == null)
            vi = inflater.inflate(R.layout.item_row_homework, null);

        ImageView imgThumbnail = (ImageView) vi
                .findViewById(R.id.homework_imgThumbnail);
        TextView txtTitle = (TextView) vi
                .findViewById(R.id.homework_txtTitle);
        TextView txtSubTitle = (TextView) vi
                .findViewById(R.id.homework_txtSubTitle);

        imgThumbnail.setImageResource(item.ThumbnailResource);
        txtTitle.setText(item.Title);
        txtSubTitle.setText(item.SubTitle);
    }
    if (item.Type.equals("Study")) {

        if (convertView == null)
            vi = inflater.inflate(R.layout.item_row_study, null);

        ImageView imgThumbnail = (ImageView) vi
                .findViewById(R.id.study_imgThumbnail);
        TextView txtTitle = (TextView) vi
                .findViewById(R.id.study_txtTitle);
        TextView txtSubTitle = (TextView) vi
                .findViewById(R.id.study_txtSubTitle);

        imgThumbnail.setImageResource(item.ThumbnailResource);
        txtTitle.setText(item.Title);
        txtSubTitle.setText(item.SubTitle);
    }
    if (item.Type.equals("Project")) {

        if (convertView == null)
            vi = inflater.inflate(R.layout.item_row_project, null);

        ImageView imgThumbnail = (ImageView) vi
                .findViewById(R.id.project_imgThumbnail);
        TextView txtTitle = (TextView) vi
                .findViewById(R.id.project_txtTitle);
        TextView txtSubTitle = (TextView) vi
                .findViewById(R.id.project_txtSubTitle);

        imgThumbnail.setImageResource(item.ThumbnailResource);
        txtTitle.setText(item.Title);
        txtSubTitle.setText(item.SubTitle);
    }

    return vi;
}
}

这是 logcat 的输出。

06-29 19:21:59.543: E/AndroidRuntime(2507): FATAL EXCEPTION: main
06-29 19:21:59.543: E/AndroidRuntime(2507): Process: com.example.customlistview, PID: 2507
06-29 19:21:59.543: E/AndroidRuntime(2507): java.lang.NullPointerException
06-29 19:21:59.543: E/AndroidRuntime(2507):     at com.example.customlistview.CustomListViewAdapter.getView(CustomListViewAdapter.java:68)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.widget.AbsListView.obtainView(AbsListView.java:2240)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.widget.ListView.makeAndAddView(ListView.java:1790)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.widget.ListView.fillDown(ListView.java:691)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.widget.ListView.fillGap(ListView.java:655)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.widget.AbsListView.trackMotionScroll(AbsListView.java:5136)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.widget.AbsListView.scrollIfNeeded(AbsListView.java:3236)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.widget.AbsListView.onTouchMove(AbsListView.java:3580)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.widget.AbsListView.onTouchEvent(AbsListView.java:3424)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.view.View.dispatchTouchEvent(View.java:7706)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2210)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1945)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2068)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1515)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.app.Activity.dispatchTouchEvent(Activity.java:2458)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2016)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.view.View.dispatchPointerEvent(View.java:7886)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:3954)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:3833)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3399)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3449)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3418)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3525)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3426)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3582)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3399)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3449)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3418)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3426)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3399)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5602)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:5582)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:5553)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:5682)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.view.InputEventReceiver.nativeConsumeBatchedInputEvents(Native Method)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.view.InputEventReceiver.consumeBatchedInputEvents(InputEventReceiver.java:176)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.view.ViewRootImpl.doConsumeBatchedInput(ViewRootImpl.java:5655)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.view.ViewRootImpl$ConsumeBatchedInputRunnable.run(ViewRootImpl.java:5701)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.view.Choreographer$CallbackRecord.run(Choreographer.java:761)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.view.Choreographer.doCallbacks(Choreographer.java:574)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.view.Choreographer.doFrame(Choreographer.java:542)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:747)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.os.Handler.handleCallback(Handler.java:733)
06-29 19:21:59.543: E/AndroidRuntime(2507):     at android.os.Handler.dispatchMessage(Handler.java:9

【问题讨论】:

  • 你在CustomListViewAdapter.java的第68行有一个NullPointerException。
  • @CommonsWare for reference 第 68 行是 imgThumbnail.setImageResource(item.ThumbnailResource);在第一个 if 语句下。但是,我不确定发生了什么,因为当我缓慢地完全滚动列表视图时,这段代码工作正常。
  • 我不知道是什么导致了空指针,但是如果您的 ListView 包含图像,您应该实现 ViewHolder 模式:lucasr.org/2012/04/05/performance-tips-for-androids-listview

标签: android listview android-listview android-custom-view


【解决方案1】:

您需要为您的ListAdapter 正确实现getViewTypeCount() 和getItemViewType()。

getViewTypeCount() 需要返回 distinct 行类型的数量(在您的情况下,它似乎是 3)。

getItemViewType() 然后需要返回一个数字,从 0 到getViewTypeCount()-1,表示提供的position 对应的视图类型。在您的情况下,您将返回 0、1 或 2,具体取决于这是 Homework、Study 还是 Project 行。

如果你正确地实现这些,传递给getView() 的convertView 将是该行的正确类型。现在,您假设convertView 的类型正确,如果不是,您的findViewById() 查找将失败。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多