完全无响应的 Android 自定义适配器

Posted

技术标签:

【中文标题】完全无响应的 Android 自定义适配器【英文标题】:Completely Unresponsive Android Custom Adapter 【发布时间】:2015-06-25 00:04:06 【问题描述】:

似乎无法确定我的适配器的问题。我试图在checkedTextView 下方放置一个进度条,以尽量减少元素数量和相对布局的麻烦(将加载栏放在下方,将单选按钮放在textView 的右侧)。

protected void onCreate(Bundle savedInstanceState)

...
    connections = new ArrayList<WifiP2pClient>();//make an arraylist for the connections
    listView = (ListView)findViewById(R.id.connectionsListView);//initialize the list view
    adapter = new P2PClientArrayAdapter(this, android.R.layout.simple_List_item_single_choice, connections);//create an array adapter
    listView.setAdapter(adapter);//attach the adapter to the listView
    listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
...


public class P2PClientArrayAdapter extends ArrayAdapter<WifiP2pClient>

    private CheckedTextView checkedTextView;
    private ProgressBar progressBar;
    int lastRadioButtonPressed;
    CheckedTextView lastPressedTextView;
    public P2PClientArrayAdapter(Context context, int resource, List<WifiP2pClient> clients)
    
        super(context, resource, clients);
        lastRadioButtonPressed = -1;
        lastPressedTextView = null;
    
    @Override
    public View getView(final int position, View convertView, ViewGroup parent)
    
        View row = convertView;
        WifiP2pClient client = getItem(position);
        if(row == null)
        
            LayoutInflater inflater = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            row = inflater.inflate(R.layout.row_layout, parent, false);

            checkedTextView = (CheckedTextView)row.findViewById(R.id.clientToString);
            progressBar = (ProgressBar)row.findViewById(R.id.clientProgressBar);

            row.setOnClickListener(new View.OnClickListener()
            
                @Override
                public void onClick(View v)
                
                    if(position != lastRadioButtonPressed)
                    
                        if(lastPressedTextView != null)
                        
                            lastPressedTextView.setChecked(false);
                        
                        lastRadioButtonPressed = position;
                        lastPressedTextView = checkedTextView;
                        checkedTextView.setChecked(true);
                        P2PClientArrayAdapter.this.notifyDataSetChanged();
                    
                
            );
        
        checkedTextView.setText(client.toString());
        progressBar.setProgress(client.getProgress());
        return row;
    

目前,问题是适配器无响应。我使用异步任务更新WifiP2pClient 并经常调用notifyDataSetChanged(),但UI 中显示的数据永远不会更新。此外,当我按下listView 时,什么也没有发生(甚至没有正常的黑色压下动画)。

如果我改用常规的ArrayListAdapter&lt;String&gt; 对象,arrayList 会正确更新,所以我知道其余代码可以正常工作,这 arrayAdapter 有问题。

编辑:我根据这篇文章将onClickListener() 放入getView(): How to use RadioGroup in ListView custom adapter?

EDIT2:通过使用@987654336 确保在视图不为空时正确更新checkedViewTextprogressBar 对象,我让适配器正确响应对其所做的更改和用户的按下@object 和视图的 setTag()getTag() 功能。我将很快粘贴此代码。但是,我仍然没有让适配器为 getCheckedItemPosition() 返回正确的值。

【问题讨论】:

为什么要将 onclicklistener 放在适配器的 getView() 中?它应该在适配器本身上。 也许您可以将代码发布到您使用新数据更新适配器的位置? 【参考方案1】:

在做了足够多的实验并幸运地休息之后,这是我完成的代码(为了将来的谷歌用户和比较起见)。

public class P2PClientArrayAdapter extends ArrayAdapter<WifiP2pClient>

    //The viewholder object isn't neccessary but it allows us to Tag.set()
    //with no indicies because we have it wrapped in one big object
    private class ViewHolder
    
        CheckedTextView checkedTextView;
        ProgressBar progressBar;
    

    int lastRadioButtonPressed;
    CheckedTextView lastPressedTextView;

    public P2PClientArrayAdapter(Context context, int resource, List<WifiP2pClient> clients)
    
        super(context, resource, clients);
        lastRadioButtonPressed = -1;
        lastPressedTextView = null;
    

    //I wasn't sure how to override ListView's getCheckedItemPosition()
    //So I made my own and then changed the calling code.
    public int getCheckedItemPosition()
    
        return lastRadioButtonPressed;
    
    //If you delete an element in your list, you have 
    //to reset the pointer or you'll have logic errors.
    public void resetCheckedItemPosition()
    
        lastRadioButtonPressed = -1;
        lastPressedTextView = null;
    

    @Override
    public View getView(final int position, View convertView, ViewGroup parent)
    
        View row = convertView;
        WifiP2pClient client = getItem(position);

        final ViewHolder viewHolder;

        if(row == null)
        
            LayoutInflater inflater = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            row = inflater.inflate(R.layout.row_layout, parent, false);

            viewHolder = new ViewHolder();
            viewHolder.checkedTextView = (CheckedTextView)row.findViewById(R.id.clientToString);
            viewHolder.progressBar = (ProgressBar)row.findViewById(R.id.clientProgressBar);

            row.setTag(viewHolder);
        
        else
        
            viewHolder = (ViewHolder)row.getTag();
        
        row.setOnClickListener(new View.OnClickListener()
        
            @Override
            public void onClick(View v)
            
                if(position != lastRadioButtonPressed)
                
                    if(lastPressedTextView != null)
                    
                        lastPressedTextView.setChecked(false);
                    
                    lastRadioButtonPressed = position;
                    lastPressedTextView = viewHolder.checkedTextView;
                    viewHolder.checkedTextView.setChecked(true);
                
            
        );
        viewHolder.checkedTextView.setText(client.toString());
        viewHolder.progressBar.setProgress(client.getProgress());
        return row;
    

【讨论】:

以上是关于完全无响应的 Android 自定义适配器的主要内容,如果未能解决你的问题,请参考以下文章

自定义pam登陆验证方式后,xftp工具使用无响应

IBM MFP8 - 调用适配器时主机无响应错误

如何强制关闭Ubuntu无响应程序

请求接口无响应

Android 应用程序无响应

自定义 UIButton + 子视图 = 无事件