web-dev-qa-db-ja.com

バターナイフがアダプタクラス内でバインドできない

ナビゲーションドロワーのレイアウトを描画するアダプターがあります。私のナビゲーションドロワーには、2つの内部xmlファイルが含まれています。1つはHeaderで、もう1つはRowです。これらを単一のアダプターで引き出しますが、ヘッダーでsetText()をしようとすると、バインドに失敗します。これが私のアダプタクラスです:

public class DrawerAdapter extends RecyclerView.Adapter<DrawerAdapter.ViewHolder> {

private static final int HEADER_TYPE = 0;
private static final int ROW_TYPE = 1;
private static Context context;
private static DatabaseHelper databaseHelper;

private List<String> rows;
private List<Integer> icons;
private String driverName;

public DrawerAdapter(Context context, List<String> rows, List<Integer> icons, String driverName, DatabaseHelper databaseHelper) {
    this.icons = icons;
    this.rows = rows;
    this.context = context;
    this.driverName = driverName;
    this.databaseHelper = databaseHelper;
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    if (viewType == HEADER_TYPE) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.drawer_header, parent, false);
        return new ViewHolder(view, viewType);

    } else if (viewType == ROW_TYPE) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.drawer_row, parent, false);
        return new ViewHolder(view, viewType);
    }
    return null;
}

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
    if (holder.viewType == ROW_TYPE) {
        String rowText = rows.get(position - 1);
        int imageView = icons.get(position - 1);
        holder.textView.setText(rowText);
        holder.imageView.setImageResource(imageView);
    } else if (holder.viewType == HEADER_TYPE) {
        holder.driverNameText.setText(driverName);
    }
}

@Override
public int getItemCount() {
    return rows.size() + 1;
}

@Override
public int getItemViewType(int position) {
    if (position == 0)
        return HEADER_TYPE;
    return ROW_TYPE;
}

public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
    protected int viewType;
    @Bind(R.id.drawer_row_icon)
    ImageView imageView;
    @Bind(R.id.drawer_row_text)
    TextView textView;
    @Bind(R.id.drawer_row_id)
    FrameLayout listRow;
    @Bind(R.id.driverName)
    TextView driverNameText;

    public ViewHolder(View itemView, int viewType) {
        super(itemView);

        this.viewType = viewType;

        if (viewType == ROW_TYPE) {
            ButterKnife.bind(this, itemView);
            imageView.setOnClickListener(this);
            textView.setOnClickListener(this);
            listRow.setOnClickListener(this);
        } else {
            ButterKnife.bind(this, itemView);
        }
    }


 }

onCreateViewHolderメソッドで確認できるように、両方のviewTypeをチェックしているため、どのレイアウトを描画するかがわかります。これにより、ViewHolderクラスの新しいオブジェクトが作成され、viewTypeに応じて、XML内の要素を「TRY」してバインドします。何かが足りないのか、それとも何か間違っているのか

15
remedy.

私はこの問題を次のようにして解決することができました:

まず、APIドキュメントは次のように述べています

デフォルトでは、ビューはフィールドとメソッドの両方のバインディングのレイアウトに存在する必要があります。ビューがオプションの場合は、support-annotationsライブラリーにあるような@Nullableアノテーションを追加します。

@Nullable @Bind(R.id.title) TextView subtitleView;

http://jakewharton.github.io/butterknife/javadoc/

異なるxmlファイルからのバインドする異なる要素があったので、そもそもそれらがバインド可能でさえない可能性があるので、それらを@Nullableとしてタグ付けする必要がありました。コードを次のように変更しました。

_@Nullable @Bind(R.id.drawer_row_icon)
ImageView imageView;
@Nullable @Bind(R.id.drawer_row_text)
TextView textView;
@Nullable @Bind(R.id.drawer_row_id)
FrameLayout listRow;
@Nullable @Bind(R.id.driverName)
TextView driverNameText;
_

また、ButterKnife.bind()を_IF-ELSE_ブロックの外に移動しています。

25
remedy.

あなたは2回拘束しています。同じビューでbindを2回呼び出すことはできません。これは、findviewbyid呼び出しのみを実行しています。 ifブロックの上でbindを1回呼び出します。

public ViewHolder(View itemView, int viewType) {
    super(itemView);

    this.viewType = viewType;

    ButterKnife.bind(this, itemView);
    if (viewType == ROW_TYPE) {
        imageView.setOnClickListener(this);
        textView.setOnClickListener(this);
        listRow.setOnClickListener(this);
    }
}
6
doubleA