Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/391.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/visual-studio/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java &引用;变量是从内部类中访问的,需要声明为final;自定义适配器中出现错误_Java_Android_Custom Adapter - Fatal编程技术网

Java &引用;变量是从内部类中访问的,需要声明为final;自定义适配器中出现错误

Java &引用;变量是从内部类中访问的,需要声明为final;自定义适配器中出现错误,java,android,custom-adapter,Java,Android,Custom Adapter,我正试图实现一个带有复选框的多选列表视图,并定义了一个自定义适配器类,如下所示: package com.ameer.easycooking; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.w

我正试图实现一个带有复选框的多选列表视图,并定义了一个自定义适配器类,如下所示:

package com.ameer.easycooking;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

public class CategoryAdapter extends ArrayAdapter<String> {

    private List<String> categoryList;
    private Context context;
    private List<String> selected = new ArrayList<>();

    public CategoryAdapter(List<String> categoryList, Context context) {
        super(context, R.layout.category_list_item, categoryList);
        this.categoryList = categoryList;
        this.context = context;
    }

    public static class CategoryHolder {
        private CheckBox checkBox;
        private TextView categoryName;

        public CategoryHolder(CheckBox checkBox, TextView categoryName) {
            this.checkBox = checkBox;
            this.categoryName = categoryName;
        }

        public CheckBox getCheckBox() {
            return checkBox;
        }

        public void setCheckBox(CheckBox checkBox) {
            this.checkBox = checkBox;
        }

        public TextView getCategoryName() {
            return categoryName;
        }

        public void setCategoryName(TextView categoryName) {
            this.categoryName = categoryName;
        }
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View v = convertView;

        CategoryHolder holder = new CategoryHolder((CheckBox) v.findViewById(R.id.checkBox), (TextView) v.findViewById(R.id.name));

        if (convertView == null) {
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            v = inflater.inflate(R.layout.category_list_item, null);

            holder.getCheckBox().setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                        if (isChecked) {
                            selected.add(holder.getCheckBox().getText().toString());
                        }else{
                            selected.remove(holder.getCheckBox().getText().toString());
                        }
                }
            });
            v.setTag(holder);
        } else {
            holder = (CategoryHolder) v.getTag();
        }

        String category = categoryList.get(position);
        holder.categoryName.setText(category);
        holder.checkBox.setTag(category);

        return v;
    }

    public List<String> getSelected() {
        return selected;
    }
}
package com.ameer.easycooking;
导入android.content.Context;
导入android.view.LayoutInflater;
导入android.view.view;
导入android.view.ViewGroup;
导入android.widget.ArrayAdapter;
导入android.widget.CheckBox;
导入android.widget.CompoundButton;
导入android.widget.TextView;
导入java.util.ArrayList;
导入java.util.List;
公共类CategoryAdapter扩展了ArrayAdapter{
私有列表分类列表;
私人语境;
所选私有列表=新建ArrayList();
公共类别适配器(列表类别列表、上下文){
super(上下文、R.layout.category\u list\u项、categoryList);
this.categoryList=categoryList;
this.context=上下文;
}
公共静态类类别文件夹{
私有复选框;
私有TextView类别名称;
公共类别文件夹(文本视图类别名称复选框){
this.checkBox=复选框;
this.categoryName=categoryName;
}
公共复选框getCheckBox(){
返回复选框;
}
公共无效设置复选框(复选框){
this.checkBox=复选框;
}
公共文本视图getCategoryName(){
返回类别名称;
}
公共无效setCategoryName(TextView categoryName){
this.categoryName=categoryName;
}
}
@凌驾
公共视图getView(int位置、视图转换视图、视图组父视图){
视图v=转换视图;
CategoryHolder holder=新的CategoryHolder((复选框)v.findViewById(R.id.CheckBox),(文本视图)v.findViewById(R.id.name));
if(convertView==null){
LayoutFlater充气器=(LayoutFlater)context.getSystemService(context.LAYOUT\u充气器\u服务);
v=充气机充气(R.layout.category\u list\u项,空);
holder.getCheckBox().setOnCheckedChangeListener(新建CompoundButton.OnCheckedChangeListener()){
@凌驾
检查更改后的公共无效(复合按钮视图,布尔值已检查){
如果(已检查){
添加(holder.getCheckBox().getText().toString());
}否则{
选中.remove(holder.getCheckBox().getText().toString());
}
}
});
v、 setTag(支架);
}否则{
holder=(CategoryHolder)v.getTag();
}
String category=categoryList.get(位置);
holder.categoryName.setText(类别);
holder.checkBox.setTag(类别);
返回v;
}
公共列表getSelected(){
返回选中的;
}
}
我想将选中的项存储在
选中的
列表中,然后在类末尾使用getter检索它们,但它告诉我需要将“holder”声明为final,如果我将其声明为final,我就不能再使用
holder=(CategoryHolder)v.getTag()为其赋值所以解决一个问题就是创建另一个问题:(我如何解决这两个问题


提前感谢。

您可以从选中的
更改侦听器的参数中获得必要的信息:
按钮视图是选中的元素。因此,您只需执行以下操作:

@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
       CheckBox checkbox;
       if (buttonView instanceof CheckBox )
       {
           checkbox = (CheckBox)buttonView;
       }
       else return;

       if (isChecked) {
            selected.add(checkbox.getText().toString());
       }else{
            selected.remove(checkbox.getText().toString());
       }
}

若您将对象用于内部类,则应该声明它
final
。 这里解释如下:

因此,您可以将该变量设为final:

final CategoryHolder holder = convertView != null ? 
    (CategoryHolder) v.getTag() :
    new CategoryHolder((CheckBox) v.findViewById(R.id.checkBox), (TextView) v.findViewById(R.id.name));

您的holder是一个内部类。您需要将其声明为全局变量,然后在需要时对其进行初始化。我按照您的建议更改了代码,但现在在
CategoryHolder holder=new CategoryHolder((CheckBox)v.findViewById(R.id.CheckBox),(TextView)v.findViewById(R.id.name))处出现空指针异常
为什么?@user3501779-很高兴听到我的回答让你更进一步:至少现在它正在运行…不知何故;-)你得到了一个NPE,因为
convertView
有时可能是
null
。因此,如果将
null
分配给
v
,则
v.findViewById()
会导致NPE。根据此信息,我将上行移到
if(convertView==null)
条件中,它现在正在工作并在ListView中显示项目。但是,我总是在所选的
中得到一个空字符串。
getText()
方法是否返回复选框文本或文本视图文本?我想这就是问题所在,因为我没有给复选框文本分配任何内容,而是给相应的文本视图。解决了它。我应该在复选框中使用
setText()
,而不是
setTag()
,因此现在我还可以完全忽略适配器中的文本视图。非常感谢你@user3501779-不客气:)请记住,通过使用
View.getTag(),您也可以从复选框中检索类别(即使不强制转换)。toString()
标记有时非常方便