2012-05-09 32 views
2

我试图创建一个具有多种类型的视图的ListView适配器。我下面的下面的教程:Android ListView - 奇怪的回收行为

http://android.amberfog.com/?p=296

然而,第一轮建设下面的代码后:

public class MultipleItemList extends Activity 
{ 
    private MyCustomAdapter mAdapter; 
    private ListView  mListView; 
    private String   mTag = "MultipleItemList"; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) 
    { 
    super.onCreate(savedInstanceState); 

    setContentView(R.layout.main); 

    mListView = (ListView)findViewById(R.id.main_list); 

    mAdapter = new MyCustomAdapter(); 

    for(int i = 0; i < 50; i++) 
    { 
     mAdapter.addItem("Item: " + i); 
    } 

    mListView.setAdapter(mAdapter); 
    } 

    private class MyCustomAdapter extends BaseAdapter 
    { 
    private ArrayList<String> mData = new ArrayList<String>(); 
    private LayoutInflater mInflater; 

    public MyCustomAdapter() 
    { 
     mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
    } 

    public void addItem(final String item) 
    { 
     mData.add(item); 
     notifyDataSetChanged(); 
    } 

    public int getCount() 
    { 
     return mData.size(); 
    } 

    public String getItem(int position) 
    { 
     return mData.get(position); 
    } 

    public long getItemId(int position) 
    { 
     return position; 
    } 

    public View getView(int position, View convertView, ViewGroup parent) 
    { 
     Log.e(mTag, "getView: " + position + " " + convertView); 

     ViewHolder holder = null; 

     if(convertView == null) 
     { 
     convertView = mInflater.inflate(R.layout.list_item, null); 

     holder = new ViewHolder(); 

     holder.textView = (TextView)convertView.findViewById(R.id.item_text); 

     convertView.setTag(holder); 
     } 
     else 
     { 
     holder = (ViewHolder)convertView.getTag(); 
     } 

     holder.textView.setText(mData.get(position)); 

     return convertView; 
    } 
    } 

    public static class ViewHolder 
    { 
    public TextView textView; 
    } 

} 

凡的main.xml是:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:orientation="vertical" > 

    <ListView 
     android:id="@+id/main_list" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" > 
    </ListView> 

</LinearLayout> 

而list_item.xml是:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:orientation="vertical" > 

    <TextView 
     android:id="@+id/item_text" 
     android:layout_width="fill_parent" 
     android:layout_height="50dp" 
     android:text="TextView" 
     android:gravity="center_vertical" 
     android:paddingLeft="25dp"/> 

</LinearLayout> 

我期望的输出类似于他的预期输出:

02-05 13:47:32.559: INFO/System.out(947): getView 0 null 
02-05 13:47:32.570: INFO/System.out(947): getView 1 null 
02-05 13:47:32.589: INFO/System.out(947): getView 2 null 
02-05 13:47:32.599: INFO/System.out(947): getView 3 null 
02-05 13:47:32.619: INFO/System.out(947): getView 4 null 
02-05 13:47:32.629: INFO/System.out(947): getView 5 null 
02-05 13:47:32.708: INFO/System.out(947): getView 6 null 
02-05 13:47:32.719: INFO/System.out(947): getView 7 null 
02-05 13:47:32.729: INFO/System.out(947): getView 8 null 

而是没有用户交互,只需加载屏幕,我得到以下几点:

05-09 15:24:00.347: E/MultipleItemList(11109): getView: 0 null 
05-09 15:24:00.357: E/MultipleItemList(11109): getView: 1 [email protected] 
05-09 15:24:00.357: E/MultipleItemList(11109): getView: 2 [email protected] 
05-09 15:24:00.357: E/MultipleItemList(11109): getView: 3 [email protected] 
05-09 15:24:00.357: E/MultipleItemList(11109): getView: 4 [email protected] 
05-09 15:24:00.357: E/MultipleItemList(11109): getView: 5 [email protected] 
05-09 15:24:00.367: E/MultipleItemList(11109): getView: 6 [email protected] 
05-09 15:24:00.367: E/MultipleItemList(11109): getView: 7 [email protected] 
05-09 15:24:00.367: E/MultipleItemList(11109): getView: 8 [email protected] 
05-09 15:24:00.367: E/MultipleItemList(11109): getView: 9 [email protected] 
05-09 15:24:00.407: E/MultipleItemList(11109): getView: 0 [email protected] 
05-09 15:24:00.407: E/MultipleItemList(11109): getView: 1 null 
05-09 15:24:00.407: E/MultipleItemList(11109): getView: 2 null 
05-09 15:24:00.417: E/MultipleItemList(11109): getView: 3 null 
05-09 15:24:00.417: E/MultipleItemList(11109): getView: 4 null 
05-09 15:24:00.417: E/MultipleItemList(11109): getView: 5 null 
05-09 15:24:00.427: E/MultipleItemList(11109): getView: 6 null 
05-09 15:24:00.427: E/MultipleItemList(11109): getView: 7 null 
05-09 15:24:00.437: E/MultipleItemList(11109): getView: 8 null 
05-09 15:24:00.437: E/MultipleItemList(11109): getView: 9 null 
05-09 15:24:00.457: E/MultipleItemList(11109): getView: 0 null 
05-09 15:24:00.457: E/MultipleItemList(11109): getView: 1 [email protected] 
05-09 15:24:00.457: E/MultipleItemList(11109): getView: 2 [email protected] 
05-09 15:24:00.457: E/MultipleItemList(11109): getView: 3 [email protected] 
05-09 15:24:00.457: E/MultipleItemList(11109): getView: 4 [email protected] 
05-09 15:24:00.457: E/MultipleItemList(11109): getView: 5 [email protected] 
05-09 15:24:00.467: E/MultipleItemList(11109): getView: 6 [email protected] 
05-09 15:24:00.467: E/MultipleItemList(11109): getView: 7 [email protected] 
05-09 15:24:00.467: E/MultipleItemList(11109): getView: 8 [email protected] 
05-09 15:24:00.467: E/MultipleItemList(11109): getView: 9 [email protected] 

为什么地球上有很多工作要呈现列表中的前10个项目?发生

+0

我可以在代码和教程中的代码之间看到的唯一真正区别是本教程使用“ListActivity”而不是“Activity”。 “Activity”和“ListActivity”中的ListView行为之间可能存在细微的差异。如果你完全按照教程做,你会得到相同的结果吗? – Louth

+0

@Louth:我不确定。我不打算在我的应用程序中使用ListActivity,所以我不知道这太值得探索了。我认为不管ListActivity“活着”在哪里,行为都不应该偏离。 – Josh

+1

可能的重复:http://stackoverflow.com/questions/2618272/custom-listview-adapter-getview-method-being-called-multiple-times-and-in-no-co –

回答

2

Activity看到的来电getView和教程看到getView的调用之间的差异,因为本教程采用的是ListActivity。在使用不同的活动类时调用Adapters的方式存在一些根本区别。

我把你的问题中的代码代码,并能够重现你报告的日志。当我将其改为从ListActivity扩展时,我能够重现教程中看到的日志。

展望StackTraceElements为getView()我可以看到以下内容:

活动日志

getView: pos[0] convertView[null] 
CallerClass[android.widget.AbsListView] CallerMethod[obtainView] 
CallerClass[android.widget.ListView] CallerMethod[measureHeightOfChildren] 
CallerClass[android.widget.ListView] CallerMethod[onMeasure] 
CallerClass[android.view.View] CallerMethod[measure] 
CallerClass[android.view.ViewGroup] CallerMethod[measureChildWithMargins] 
CallerClass[android.widget.LinearLayout] CallerMethod[measureChildBeforeLayout] 
CallerClass[android.widget.LinearLayout] CallerMethod[measureVertical] 
CallerClass[android.widget.LinearLayout] CallerMethod[onMeasure] 
CallerClass[android.view.View] CallerMethod[measure] 
CallerClass[android.view.ViewGroup] CallerMethod[measureChildWithMargins] 
CallerClass[android.widget.FrameLayout] CallerMethod[onMeasure] 
CallerClass[android.view.View] CallerMethod[measure] 
CallerClass[android.widget.LinearLayout] CallerMethod[measureVertical] 
CallerClass[android.widget.LinearLayout] CallerMethod[onMeasure] 
CallerClass[android.view.View] CallerMethod[measure] 
CallerClass[android.view.ViewGroup] CallerMethod[measureChildWithMargins] 
CallerClass[android.widget.FrameLayout] CallerMethod[onMeasure] 
CallerClass[com.android.internal.policy.impl.PhoneWindow$DecorView] CallerMethod[onMeasure] 
CallerClass[android.view.View] CallerMethod[measure] 
CallerClass[android.view.ViewRootImpl] CallerMethod[performTraversals] 
CallerClass[android.view.ViewRootImpl] CallerMethod[handleMessage] 
CallerClass[android.os.Handler] CallerMethod[dispatchMessage] 
CallerClass[android.os.Looper] CallerMethod[loop] 
CallerClass[android.app.ActivityThread] CallerMethod[main] 
CallerClass[java.lang.reflect.Method] CallerMethod[invokeNative] 
CallerClass[java.lang.reflect.Method] CallerMethod[invoke] 
CallerClass[com.android.internal.os.ZygoteInit$MethodAndArgsCaller] CallerMethod[run] 
CallerClass[com.android.internal.os.ZygoteInit] CallerMethod[main] 
CallerClass[dalvik.system.NativeStart] CallerMethod[main] 

ListActivity.log

getView: pos[0] convertView[null] 
CallerClass[android.widget.AbsListView] CallerMethod[obtainView] 
CallerClass[android.widget.ListView] CallerMethod[makeAndAddView] 
CallerClass[android.widget.ListView] CallerMethod[fillDown] 
CallerClass[android.widget.ListView] CallerMethod[fillFromTop] 
CallerClass[android.widget.ListView] CallerMethod[layoutChildren] 
CallerClass[android.widget.AbsListView] CallerMethod[onLayout] 
CallerClass[android.view.View] CallerMethod[layout] 
CallerClass[android.view.ViewGroup] CallerMethod[layout] 
CallerClass[android.widget.FrameLayout] CallerMethod[onLayout] 
CallerClass[android.view.View] CallerMethod[layout] 
CallerClass[android.view.ViewGroup] CallerMethod[layout] 
CallerClass[android.widget.LinearLayout] CallerMethod[setChildFrame] 
CallerClass[android.widget.LinearLayout] CallerMethod[layoutVertical] 
CallerClass[android.widget.LinearLayout] CallerMethod[onLayout] 
CallerClass[android.view.View] CallerMethod[layout] 
CallerClass[android.view.ViewGroup] CallerMethod[layout] 
CallerClass[android.widget.FrameLayout] CallerMethod[onLayout] 
CallerClass[android.view.View] CallerMethod[layout] 
CallerClass[android.view.ViewGroup] CallerMethod[layout] 
CallerClass[android.view.ViewRootImpl] CallerMethod[performTraversals] 
CallerClass[android.view.ViewRootImpl] CallerMethod[handleMessage] 
CallerClass[android.os.Handler] CallerMethod[dispatchMessage] 
CallerClass[android.os.Looper] CallerMethod[loop] 
CallerClass[android.app.ActivityThread] CallerMethod[main] 
CallerClass[java.lang.reflect.Method] CallerMethod[invokeNative] 
CallerClass[java.lang.reflect.Method] CallerMethod[invoke] 
CallerClass[com.android.internal.os.ZygoteInit$MethodAndArgsCaller] CallerMethod[run] 
CallerClass[com.android.internal.os.ZygoteInit] CallerMethod[main] 
CallerClass[dalvik.system.NativeStart] CallerMethod[main] 

所以,我的回答将是的方式有很大的不同在不同的活动类型中被填充/呈现,并且这导致对getView的调用量的差异。

+1

这和我在帖子中评论中提到的答案是问题所在。当你不使用fill_parent来实现ListView的宽度和高度时(正如我猜测扩展ListActivity所做的那样),Android必须在不渲染的情况下对整个列表进行布局,以便可以对其进行测量,然后开始渲染。填充或匹配父项时,尺寸是已知的。 – Josh