使用ListView适配器和ViewHolders崩溃

时间:2014-01-06 16:34:18

标签: android listview

以下是Android游戏中列表视图的适配器类代码 列表视图显示3种类型的行: 1)完成水平 2)进展水平 3)锁定级别

我尝试使用回收器尽可能减少内存泄漏。 使用此代码时,我遇到了崩溃(见下文)。当我向下滚动列表并且在列表中遇到锁定级别时发生崩溃。显示inprogress级别工作正常。 我认为我对持有者的类别做错了,但我不知道是什么。 谢谢你看这个案子。

下面的崩溃:

    01-06 17:11:26.023: E/AndroidRuntime(2943): FATAL EXCEPTION: main
    01-06 17:11:26.023: E/AndroidRuntime(2943): java.lang.ClassCastException: com.Adptr_List$ViewHolderInProgress cannot be cast to com.Adptr_List$ViewHolderLocked
    01-06 17:11:26.023: E/AndroidRuntime(2943):     at com.Adptr_List.getView(Adptr_List.java:302)
    01-06 17:11:26.023: E/AndroidRuntime(2943):     at android.widget.HeaderViewListAdapter.getView(HeaderViewListAdapter.java:220)
    01-06 17:11:26.023: E/AndroidRuntime(2943):     at android.widget.AbsListView.obtainView(AbsListView.java:2255)
    01-06 17:11:26.023: E/AndroidRuntime(2943):     at android.widget.ListView.makeAndAddView(ListView.java:1769)
    01-06 17:11:26.023: E/AndroidRuntime(2943):     at android.widget.ListView.fillDown(ListView.java:672)
    01-06 17:11:26.023: E/AndroidRuntime(2943):     at android.widget.ListView.fillGap(ListView.java:636)
    01-06 17:11:26.023: E/AndroidRuntime(2943):     at android.widget.AbsListView.trackMotionScroll(AbsListView.java:5040)
    01-06 17:11:26.023: E/AndroidRuntime(2943):     at android.widget.AbsListView$FlingRunnable.run(AbsListView.java:4197)
    01-06 17:11:26.023: E/AndroidRuntime(2943):     at android.view.Choreographer$CallbackRecord.run(Choreographer.java:725)
    01-06 17:11:26.023: E/AndroidRuntime(2943):     at android.view.Choreographer.doCallbacks(Choreographer.java:555)
    01-06 17:11:26.023: E/AndroidRuntime(2943):     at android.view.Choreographer.doFrame(Choreographer.java:524)
    01-06 17:11:26.023: E/AndroidRuntime(2943):     at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:711)
    01-06 17:11:26.023: E/AndroidRuntime(2943):     at android.os.Handler.handleCallback(Handler.java:615)
    01-06 17:11:26.023: E/AndroidRuntime(2943):     at android.os.Handler.dispatchMessage(Handler.java:92)
    01-06 17:11:26.023: E/AndroidRuntime(2943):     at android.os.Looper.loop(Looper.java:137)
    01-06 17:11:26.023: E/AndroidRuntime(2943):     at android.app.ActivityThread.main(ActivityThread.java:4745)
    01-06 17:11:26.023: E/AndroidRuntime(2943):     at java.lang.reflect.Method.invokeNative(Native Method)
    01-06 17:11:26.023: E/AndroidRuntime(2943):     at java.lang.reflect.Method.invoke(Method.java:511)
    01-06 17:11:26.023: E/AndroidRuntime(2943):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
    01-06 17:11:26.023: E/AndroidRuntime(2943):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
    01-06 17:11:26.023: E/AndroidRuntime(2943):     at dalvik.system.NativeStart.main(Native Method)

我的课程代码如下:

public class Adptr_List extends ArrayAdapter<Child_Level> {

Context context;

int globalshpsfound = 0;
int currentlvlshpsfound = 0;

class ViewHolderComplete
{
    public TextView tvtitle;
    public TextView tvsubtitle;
    public ProgressBar pb;
    public TextView shpprogress;

    public ViewHolderComplete(
            TextView tvtitle,
            TextView tvsubtitle, 
            ProgressBar pb,
            TextView shpprogress) {
    }       
}

class ViewHolderInProgress
{
    public TextView tvtitle;
    public TextView tvsubtitle;
    public ProgressBar pb;
    public TextView shpprogress;
    public TextView tvPlay;

    public ViewHolderInProgress(
            TextView tvtitle,
            TextView tvsubtitle, 
            ProgressBar pb,
            TextView shpprogress,
            TextView tvPlay) {
    }
}

class ViewHolderLocked
{
    public TextView tvtitle;
    public TextView tvsubtitle;
    public TextView tvmontounlock;

    public ViewHolderLocked(
            TextView tvtitle,
            TextView tvsubtitle, 
            TextView tvmontounlock) {
    }
}

//Initialize adapter
public Adptr_List(Context context, int resource, List<Child_Level> items) {
    super(context, resource, items);

    SharedPreferences sPrefs = PreferenceManager.getDefaultSharedPreferences(getContext());   

    globalshpsfound = sPrefs.getInt("globalshpsfound", 0);          
}    


@Override
public View getView(int position, View convertView, ViewGroup parent)
{               
    SharedPreferences sPrefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 

    final Child_Level l = getItem(position);

    currentlvlshpsfound = sPrefs.getInt("foundshps_lvl_"+l.lvlid, 0);
    globalshpsfound = sPrefs.getInt("globalshpsfound", 0);

    // COMPLETE
    if (sPrefs.getInt("foundshps_lvl_"+l.lvlid, 0) == l.shpamount) {

        ViewHolderComplete holdercomplete;   
        View resultview;
        View myconvertview;

        if(convertView==null){

            ViewGroup viewGroup = (ViewGroup)LayoutInflater.from(getContext()).inflate(R.layout.inflt_lvl_complete, null);                              

            //using the ViewHolder pattern to reduce lookups
            holdercomplete = new ViewHolderComplete(
                    (TextView)viewGroup.findViewById(R.id.tvLevel_title),
                    (TextView)viewGroup.findViewById(R.id.tvLevel_subtitle),
                    (ProgressBar) viewGroup.findViewById(R.id.pbLevel_progress),
                    (TextView) viewGroup.findViewById(R.id.tvLevel_progress));

            viewGroup.setTag(holdercomplete);
            resultview = viewGroup;
        }

        else{
            holdercomplete = (ViewHolderComplete) convertView.getTag();
            resultview=convertView;
        }


        // ...here iam setting text and images

        return resultview;
        }

    // IN PROGRESS
    else if (sPrefs.getInt("globalshpsfound", 0)>=l.shptounlock || 
            (sPrefs.getBoolean("bought_lvl_"+l.lvlid, false)==true)){

        ViewHolderInProgress holderinprogress; 
        View resultview;
        View myconvertview;

        if(convertView==null){

            ViewGroup viewGroup = (ViewGroup)LayoutInflater.from(getContext()).inflate(R.layout.inflt_lvl_inprogress, null);


            //using the ViewHolder pattern to reduce lookups
            holderinprogress = new ViewHolderInProgress(
                    (TextView)viewGroup.findViewById(R.id.tvLevel_title),
                    (TextView)viewGroup.findViewById(R.id.tvLevel_subtitle),
                    (ProgressBar) viewGroup.findViewById(R.id.pbLevel_progress),
                    (TextView) viewGroup.findViewById(R.id.tvLevel_progress),
                    (TextView) viewGroup.findViewById(R.id.tvLevel_play));


            viewGroup.setTag(holderinprogress);
            resultview = viewGroup;
        }

        else {
            holderinprogress = (ViewHolderInProgress) convertView.getTag();
            resultview=convertView;
        }

        // ...here iam setting text and images

        return resultview;
        }   



    // LOCKED
    else {
        ViewHolderLocked holderlocked;  
        View resultview;
        View myconvertview;

        if(convertView==null){

            ViewGroup viewGroup = (ViewGroup)LayoutInflater.from(getContext()).inflate(R.layout.inflt_lvl_locked, null);                

            //using the ViewHolder pattern to reduce lookups
            holderlocked = new ViewHolderLocked(
                    (TextView)viewGroup.findViewById(R.id.tvLevel_title),
                    (TextView)viewGroup.findViewById(R.id.tvLevel_subtitle),
                    (TextView)viewGroup.findViewById(R.id.tvLevel_montounlock));
            //holderlocked = new ViewHolder();


            viewGroup.setTag(holderlocked);
            resultview = viewGroup;
        }

        else{
            holderlocked = (ViewHolderLocked) convertView.getTag();
            resultview=convertView;
        }

        // ...here iam setting text and images

        return resultview;
    }
}

}

3 个答案:

答案 0 :(得分:1)

您需要实现方法getViewTypeCount并返回不同单元格类型的数量,在您的情况下为3。

详细答案:

Android ListView with different layouts for each row

答案 1 :(得分:0)

最好只使用一个ViewHolder。在某些情况下将某些字段留空,但保持相同。 不要从同一函数返回不同类型的ViewHolder。

答案 2 :(得分:0)

好的我找到了一个使用getitemviewtype的解决方案:

    public int getItemViewType(int position) {


    SharedPreferences sPrefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 

    if (sPrefs.getInt(somedata stored in sharedpref) 
        return 0;

    else if (somedata stored in sharedpref) 
        return 1;

    else 
        return 2;
}

显然,pb是由sharedprefs数据与适配器每一行的子视图之间的混合引起的。 出于某种原因,在getview中混合它们不起作用,但使用getitemviewtype分离它们。