ViewHolder的数据已被绑定,但为什么小部件不会更新?

时间:2016-06-06 20:50:07

标签: android recycler-adapter android-viewholder

我们的MainActivity的TabLayout实例化了这个Fragment,它有一个RecyclerView,每个单独的项目都是CardView。从后端服务器检索数据并更新适配器。适配器绑定到ViewHolder,ViewHolder应该使用服务器的数据更新每个CardView的小部件。

这是愿景,但ViewHolder并未更新CardView的TextView小部件。它仍然显示布局xml中的默认硬编码值。

为了测试,我在Adapter和ViewHolder中添加了断点和Log语句并逐步完成。一切都很好看。

到处都放了Log语句,它记录了正确的数据。

如果数据绑定看起来很好并且没有其他错误,那么为什么ViewHolder的bindModel方法不会更新TextView?

public class ModelsFragment extends Fragment {

private final String API_KEY = "INSERT API KEY HERE";

private static final String ARG_CATEGORY = "model_category";
private String mCategory;

private RecyclerView mModelRecyclerView;
private ModelAdapter mModelAdapter;

private List<Model> mModels;

public static Fragment newInstance(String category) {
    Bundle args = new Bundle();
    args.putString(ARG_CATEGORY, category);
    ModelsFragment modelsFragment = new ModelsFragment();
    modelsFragment.setArguments(args);

    return modelsFragment;
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mCategory = getArguments().getString(ARG_CATEGORY);

    final ProgressDialog progressDialog = new ProgressDialog(getActivity(), R.style.ProgressDialogTheme);
    progressDialog.setCancelable(false);
    progressDialog.setProgressStyle(android.R.style.Widget_ProgressBar);
    progressDialog.show();

    EdmundsService service = EdmundsServiceGenerator.createService(EdmundsService.class);

    Map<String, String> options = new HashMap<>();
    options.put("state", "new");
    options.put("year", "2016");
    options.put("view", "basic");
    options.put("api_key", API_KEY);
    if (mCategory != null) {
        options.put("category", mCategory);
    }

    // Use the hash map to actually query the backend API server with a GET request.
    Call<Models> call = service.getModels(options);
    call.enqueue(new Callback<Models>() {
        @Override
        public void onResponse(Call<Models> call, Response<Models> response) {
            if (response.isSuccessful()) {
                mModels = response.body().getModels();
                progressDialog.dismiss();
                updateUI();
                Log.i("GET Status", "Successfully retrieved data");
                Log.i("GET Status", response.body().getModelsCount().toString());
            }
            else {
                Log.i("GET Status", "Failed to retrieve data");
            }
        }

        @Override
        public void onFailure(Call<Models> call, Throwable t) {
            Log.e("Error retrieving data", t.getMessage());
        }
    });
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    mModelRecyclerView = (RecyclerView) inflater.inflate(R.layout.fragment_models, container, false);
    mModelRecyclerView.setHasFixedSize(true);
    mModelRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));

    updateUI();

    return mModelRecyclerView;
}

private void updateUI() {
    mModelAdapter = new ModelAdapter(mModels);
    mModelRecyclerView.setAdapter(mModelAdapter);
}

public class ModelHolder extends RecyclerView.ViewHolder {

    private Model model;
    private TextView mName;

    public ModelHolder(LayoutInflater inflater, ViewGroup parent) {
        super(inflater.inflate(R.layout.fragment_models_card_view_item, parent, false));
        View view = inflater.inflate(R.layout.fragment_models_card_view_item, parent, false);

        mName = (TextView) view.findViewById(R.id.card_view_name);
    }

    public void bindModel(Model model) {
        this.model = model;

        // This if statement added to prevent null object reference errors.
        if (this.model != null) {
            // Data correctly logged. 
            Log.i("Inside IF statement", this.model.getName());

            mName.setText(this.model.getName()); // Why doesn't this update?
        }

        // Data correctly logged.
        Log.i("Bound model", String.valueOf(this.model.getName()));
    }

}

public class ModelAdapter extends RecyclerView.Adapter<ModelHolder> {
    // Set number of Cards in the recycler view.
    private List<Model> models;

    public ModelAdapter(List<Model> models) {
        this.models = models;
    }

    @Override
    public ModelHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new ModelHolder(LayoutInflater.from(parent.getContext()), parent);
    }

    @Override
    public void onBindViewHolder(ModelHolder holder, int position) {
        // For our list of models, get one model by position and bind it to our view holder class.
        Model model = models.get(position);

        Log.i("Just prior to binding", model.getName());

        holder.bindModel(model);
    }

    @Override
    public int getItemCount() {
        return models == null ? 0 : models.size();
    }
}
}

1 个答案:

答案 0 :(得分:0)

您在ModelHolder

中夸大了2个观看次数
public ModelHolder(LayoutInflater inflater, ViewGroup parent) {
        super(inflater.inflate(R.layout.fragment_models_card_view_item, parent, false));
        View view = inflater.inflate(R.layout.fragment_models_card_view_item, parent, false);

        mName = (TextView) view.findViewById(R.id.card_view_name);
    }

您传递给超级电话的视图是您正在显示的视图。之后您正在膨胀的视图未显示(并且您正在使用它查找mName),这就是您没有看到更改的原因。您应该只展开一个视图并将其传递到ModelHolder,以便搜索R.id.card_view_name视图。

实施例。

public ModelHolder(View view) {
        super(view);
        mName = (TextView) view.findViewById(R.id.card_view_name);
    }

并在适配器onCreateViewHolder

@Override
public ModelHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fragment_models_card_view_item, parent, false);
    return new ModelHolder(view);
}