【问题标题】:what is different between theses two context codes?这两个上下文代码有什么不同?
【发布时间】:2020-12-06 17:15:46
【问题描述】:

我在片段中使用 recyclderview。 代码 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。效果很好。

我认为它与上下文有关。但我不知道代码 1 和代码 2 有什么不同。

代码 1 和代码 2 不是都有上下文吗? 有什么不同?

【问题讨论】:

  • 为什么 3 在 2 之后? 2中发起的上下文在哪里?

标签: android android-recyclerview adapter android-context


【解决方案1】:

在 Android 中,LayoutInflater 用于将 xml 文件(activity_main.xmlfragment_login.xmlgallery_item.xml 等)转换为其对应的 View 对象。

XML 文件 -> LayoutInflater -> 在 Java 中查看对象

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

回到你的问题

代码 1

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

parent:当前项的父项,在这种情况下,parentRecyclerView

RecyclerViewView 类的子类,每个View 都有自己的上下文,在这种情况下,getContext() 返回显示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,因为它很短。

【讨论】:

  • 非常感谢。我真的明白你的解释。那么选项1、2、3到底是一样的吗?
  • 是的,它们都是一样的。
【解决方案2】:

代码 '1' 和代码 '2' 几乎相同,但是当找不到充气器时,本机实现会引发错误。我们可以打开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;
 }

【讨论】:

    【解决方案3】:

    显然你需要这样称呼:

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

    而不是这个:

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

    Context 在首次使用之前可能尚未初始化。保持变量范围尽可能紧凑是一种很好的做法,因此,如果您不需要将来自 onCreateViewHolderContext 存储在实例变量中,则不要这样做。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多