这两个上下文代码有什么不同?

what is different between theses two context codes?

我在片段中使用 recycderview。 代码 1 和代码 2 有什么区别? 当我第一次使用代码 2 和代码 3 时,它发生了错误。

@NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(parent.getContext()); // code 1

//        LayoutInflater inflater = (LayoutInflater)  context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); // code 2

        context = parent.getContext(); //code 3
        View itemView = inflater.inflate(R.layout.gallery_item, parent, false);
       
        return new ViewHolder(itemView);
    }

错误

java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object android.content.Context.getSystemService(java.lang.String)' on a null object reference
        at com.example.bstcproject.adapter.GalleryAdapter.onCreateViewHolder(GalleryAdapter.java:43)
        at com.example.bstcproject.adapter.GalleryAdapter.onCreateViewHolder(GalleryAdapter.java:23)

我留下了代码 3,我使用了代码 1 而不是代码 2。效果很好。

我认为这与上下文有关。但是不知道code 1和code 2有什么区别

code 1和code 2不是都有Context吗? 有什么不同?

代码“1”和代码“2”几乎相同,但当未找到 inflater 时,本机实现会抛出错误。我们可以打开LayoutInfalter.from方法实现并查看:

/**
 * Obtains the LayoutInflater from the given context.
 */
 public static LayoutInflater from(Context context) {
     LayoutInflater LayoutInflater =
             (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
     if (LayoutInflater == null) {
         throw new AssertionError("LayoutInflater not found.");
     }
     return LayoutInflater;
 }

在Android、LayoutInflater is used to convert an xml file (activity_main.xml, fragment_login.xml, gallery_item.xml, etc.) into its coressponding View对象中。

XML file -> LayoutInflater -> View object in Java

要检索 LayoutInflater 的实例,我们有几种选择:

回到你的问题

代码 1

LayoutInflater inflater = LayoutInflater.from(parent.getContext());

parent:当前项的父项,在本例中,parentRecyclerView

RecyclerViewView class 的子 class,每个 View 都有自己的上下文,在这种情况下,getContext() return activity 显示 RecyclerView.

代码 2

LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

在Android中,在初始化Adapter的实例时,我们通常通过构造函数传递一个Context实例,像这样。

class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private Context context;
    private List<Data> data;

    public MyAdapter(Context context, List<Data> data) {
        this.context = context;
        this.data = data;
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View itemView = inflater.inflate(R.layout.gallery_item, parent, false);
        return new ViewHolder(itemView);
    }
}

在您的情况下,因为您没有为 context 分配任何值,所以编译器会抛出该错误。

代码 3

context = parent.getContext();

在这种情况下,您不需要通过构造函数传递 Context,只需使用来自 parent.

的上下文
class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private List<Data> data;

    public MyAdapter(List<Data> data) {
        this.data = data;
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        Context context = parent.getContext();
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View itemView = inflater.inflate(R.layout.gallery_item, parent, false);
        return new ViewHolder(itemView);
    }
}

onBindViewHolder() 中,您有 3 个选项来检索 LayoutInflater 的实例:

@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    Context context = parent.getContext();

    // Option 1
    LayoutInflater inflater = LayoutInflater.from(context);

    // Option 2
    LayoutInflater inflater2 = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    // Option 3
    LayoutInflater inflater3 = ((Activity) context).getLayoutInflater();
    
    View itemView = inflater.inflate(R.layout.gallery_item, parent, false);
    return new ViewHolder(itemView);
}

我总是选择选项 1,因为它很短。

显然你需要调用这个:

LayoutInflater inflater = (LayoutInflater)  parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);

而不是这个:

LayoutInflater inflater = (LayoutInflater)  context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

因为 Context 在第一次使用之前可能还没有初始化。保持变量范围尽可能小是一种很好的做法,因此如果您不需要将 onCreateViewHolder 中的 Context 存储在实例变量中,那么就不要。