为啥我的 BaseAdapter 类不增加 getView 中的位置?

Posted

技术标签:

【中文标题】为啥我的 BaseAdapter 类不增加 getView 中的位置?【英文标题】:Why is my BaseAdapter class not incrementing the position in getView?为什么我的 BaseAdapter 类不增加 getView 中的位置? 【发布时间】:2012-07-09 07:49:06 【问题描述】:

编辑:我的问题似乎是 BaseAdapter 只是不会发布超过 1 个 Spinner。如果我将数组的大小更改为 0,它不会放任何东西,但任何超过 1 的东西都会截断它。它永远不会从getView() 传递位置 0,并且它永远不会超过 1。我已经在它上面做了几个小时。这是有原因的吗?

我在使用BaseAdapterListView 中动态添加Spinners 时遇到问题。我之前尝试过它作为测试,以确保它可以在测试类中正确完成,并且它可以正确地迭代位置。但现在我又做了一次,但它失败了。我所说的失败不是getView() 创建新的Spinner,而是永远不会离开位置0。它仍然运行。只是永远不要添加更多Spinners。 这是我的代码:

主适配器代码


public class RemindersAdapter extends BaseAdapter
Spinner[] shownReminders = new Spinner[1];
TextView[] removeReminders = new TextView[1];
String[] reminders = new String[1]; //this hlds the values of the coresponding spinner

RemindersAdapter mAdapter;


@Override
public int getCount() 
    return shownReminders.length;


@Override
public Object getItem(int position) 
    return shownReminders[position];


@Override
public long getItemId(int position) 
    return position;


@Override
public View getView(int position, View view, ViewGroup parent) 
    Log.d("TAG", "A NEW SPINNER AND TEXTVIEW IS CREATED HERE WITH POSITION"+position);
    if(view == null) 
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
        view = inflater.inflate(R.layout.reminder_spinner, parent, false);
    

    Spinner reminderSpinner = (Spinner)view.findViewById(R.id.reminder_spinner);
    reminderSpinner.setTag(String.valueOf(position));
    ArrayAdapter<CharSequence> reminderAdapter = ArrayAdapter.createFromResource(
            parent.getContext(), R.array.reminders_array, android.R.layout.simple_spinner_item);
    reminderAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    reminderSpinner.setAdapter(reminderAdapter);
    reminderSpinner.setOnItemSelectedListener(new MyOnReminderSelectedListener());
    shownReminders[position] = reminderSpinner;

    TextView remove = (TextView)view.findViewById(R.id.remove_reminder);
    remove.setTag(String.valueOf(position));
    removeReminders[position] = remove;
    remove.setOnClickListener(new View.OnClickListener() 
        @Override
        public void onClick(View v) 
            Log.d("The Array positioning of this remove view is: ", ""+v.getTag());

        
    );


    return view;



public void addReminder() 
    Log.d("addReminder METHOD", "The Add Reminder method is running");

    Spinner[] temp = new Spinner[shownReminders.length+1];
    TextView[] temp2 = new TextView[removeReminders.length+1];
    String [] temp3 = new String[reminders.length+1];
    for(int i = 0; i < shownReminders.length; i++) 
        temp[i] = shownReminders[i];
        temp2[i] = removeReminders[i];
        temp3[i] = reminders[i];
    
    shownReminders = temp;
    removeReminders = temp2;
    reminders = temp3;
    mAdapter.notifyDataSetChanged();//this just makes the adapter refresh itself



public void giveYourself(RemindersAdapter adapter) 
    mAdapter = adapter;



public class MyOnReminderSelectedListener implements OnItemSelectedListener

    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int pos,
            long id) 
        int position = Integer.parseInt(parent.getTag().toString()); //gets the position of the Spinner and puts it in the same index in the reminders array
        reminders[position] = parent.getItemAtPosition(pos).toString();
        for(int i =0; i < reminders.length; i++) Toast.makeText(parent.getContext(), i+": "+reminders[i], Toast.LENGTH_SHORT).show();
    
    @Override
    public void onNothingSelected(AdapterView<?> arg0) 
        // Do nothing for now   
       
//end of MyOnReminderSelectedListener innerclass   


//end of Class

Activity 中运行的内容


reminderList = (ListView)findViewById(R.id.reminders_list);
    reminderAdapter = new RemindersAdapter();
    reminderAdapter.giveYourself(reminderAdapter);
    reminderList.setAdapter(reminderAdapter);

    TextView addReminder = (TextView)findViewById(R.id.add_reminder);
    addReminder.setOnClickListener(new View.OnClickListener() 
        @Override
        public void onClick(View v) 
            Log.d("TAG", "The onClick is running !");
            reminderAdapter.addReminder();
        
    );

我不知所措,因为我的代码看起来与我的测试代码一模一样,只是做了一些修改才能与我的应用程序一起使用。但是Adapter 使用的信息几乎相同。我也将发布测试代码,以便你们可以看到有效的代码。

测试代码


public class RemindersAdapter extends BaseAdapter
Spinner[] shownReminders = new Spinner[1];
ArrayList<TextView> removeSpinner = new ArrayList<TextView>();
Context mContext;

public RemindersAdapter(Context context) 
    mContext = context;


@Override
public int getCount() 
    // TODO Auto-generated method stub
    return shownReminders.length;


@Override
public Object getItem(int position) 
    // TODO Auto-generated method stub
    return shownReminders[position];


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


@Override
public View getView(int position, View view, ViewGroup parent) 
    Log.d("TAG", "Number of times this is running"+position);
    Log.d("TAG", "Address of the Spinner Object"+shownReminders[position]);
    if(view == null) 
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
        view = inflater.inflate(R.layout.reminder_spinner, parent, false);
    

    Spinner reminderSpinner = (Spinner)view.findViewById(R.id.reminders_spinner);
    reminderSpinner.setTag("1"); 
    ArrayAdapter<CharSequence> reminderAdapter = ArrayAdapter.createFromResource(
            parent.getContext(), R.array.reminders_array, android.R.layout.simple_spinner_item);
    reminderAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    reminderSpinner.setAdapter(reminderAdapter);
    reminderSpinner.setOnItemSelectedListener(new MyOnReminderSelectedListener());
    shownReminders[position] = reminderSpinner;

    TextView remove = (TextView)view.findViewById(R.id.remove_reminder);
    remove.setTag(position);
    removeSpinner.add(remove);
    remove.setOnClickListener(new View.OnClickListener() 
        @Override
        public void onClick(View v) 
            int pos = Integer.parseInt(v.getTag().toString());
            removeSpinner.remove(pos);
            Spinner[] temp = new Spinner[shownReminders.length-1];
            for(int i =0; i < shownReminders.length; i++) 
                if(i == pos || i > pos) 
                    temp[i-1] = shownReminders[i];
                 else 
                    temp[i] = shownReminders[i];
                
            
            //Here i should refresh somewhow

        
    );

    return view;


public void addReminder() 
    Spinner[] temp = new Spinner[shownReminders.length+1];
    for(int i = 0; i < shownReminders.length; i++) 
        temp[i] = shownReminders[i];
    
    shownReminders = temp;



/*
 * Listener for when the reminder spinner gets a value the user entered
 * */
public class MyOnReminderSelectedListener implements OnItemSelectedListener

    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int pos,
            long id) 
        //does nothing for now

    
    @Override
    public void onNothingSelected(AdapterView<?> arg0) 
        // Do nothing for now   
       
//end of MyOnReminderSelectedListener innerclass

我还有一个问题,为什么适配器会如此频繁地自行运行。例如,使用 Log,我注意到它无缘无故地调用了两次 getView()。它有这种行为很奇怪。我想我不太了解BaseAdapter

【问题讨论】:

我不明白您为什么在内部使用另一个 ReminderAdapter,您正在调用其 notifyDataSetChanged 方法。如果您将 ReminderAdapter 的实例放入 ListView,ListView 会向您的 ReminderAdapter 注册一个 DataSetObserver。那么 mAdapter 是从哪里来的呢?是同一个例子吗?然后摆脱该成员并直接调用 notifyDataSetChanged 。如果不是同一个实例,则无法通知 ListView 更改的数据集。顺便说一句,我会使用 ArrayList 而不是用不断增长的数组重新发明*** 大声笑,它是一个指向自身的指针,所以我可以在那里刷新它,而不是在 Activity 中。我这样做是因为(这里不明显),但我偶然发现了需要在 Adapter 本身中刷新它的问题。至于 ArrayList,使用它实际上变得更加麻烦。我得到了更多的错误。由于使用size() 告诉我ArrayList 中有多少元素,我不得不使用其他方法来正确计算事物。无论哪种情况,我都尝试过,实际上工作量大致相同。此外,它只需要 3 行额外的代码。没什么大不了的 :) 谢谢你的建议。 当你点击你的文本视图时,你看到你插入的所有正确的日志输出了吗? 是的,我相信是的。但问题在于为什么getView() 方法的增量不超过零。 shownReminders 的大小正在增加:/ 但不是通过 getView。 【参考方案1】:

如果您将 ListView 放在 ScrollView 中,则会发生此错误。 ListView 本身会进行垂直滚动,因此不能将其放入 ScrollView。

【讨论】:

呃,我希望我能早点找到这篇文章。我疯了大约 30 分钟。【参考方案2】:

当 listView 需要显示新项目时,适配器将调用 getView。因此,如果您的 listView 没有滚动,则不会创建新项目,也不会调用 getView。 但是您不应该存储所有微调器对象,或在 getView 中创建新对象。那是因为它会很慢并且可能会浪费内存。

【讨论】:

如果我的 ListView 不滚动?根据我使用它的经验,情况并非如此。事实上,我必须在初始时间之后自己刷新它。我想你可能在谈论CursorAdapter。在任何情况下,getView() 会从我使用Log 看到的内容运行多次,但我实际上会尝试您刚才提到的,这是为了将我自己的观点与getView() 分开,但老实说这不是如何事情一直在运作。就像你看看我的 TestCode 一样,它可以工作!所以我很困惑。 哦,你的视图应该在getView中膨胀,但是你在getView中创建的另一个对象应该在getView之外构造,因为getView被调用了很多次。 嗯,我问你一件事。希望你有好的方法。如何获得创建的微调器列表?喜欢动态添加它们并删除它们吗?这是我的尝试。但我显然失败了。我什么都会!一整天都在做这个问题! 因为视图存储了许多与布局相关的对象,并且如果您想存储许多对象,则具有相当大的内存。您只能存储微调器的数据,并且在需要时,您可以使用该数据构造微调器。通过删除其数据来删除微调器。 我在这里遇到的问题是,即使我在getCount() 中硬编码一个数字,比如 2,getView() 中的位置将始终为 0,这意味着只有 1 号。我不知道为什么。

以上是关于为啥我的 BaseAdapter 类不增加 getView 中的位置?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的类不继承其基类中定义的方法?

为啥 weka NaiveBayes 类不实现分类实例方法?

为啥java类不从实现的接口继承注解?

解释为啥类不存储和打印输入的值

为啥这个类不编译? [复制]

为啥有些 MFC 类不是从 CObject 派生的?