0

So I have this app in which I have to make a RecyclerView which contains a list of items that can be deleted/edited e.t.c.

I followed a tutorial on youtube and I made a custom CardView item on another layout and a custom adapter for that item.

Thing is, depending on the state of the item, I have to change something(ex. background color or text color).

When I do that in the RecyclerView activity I get NullPointerException even if I have the id's.

How can I edit those TextViews inside the programmatically generated list of items in the moment I make the Retrofit call?

boolean isEnded;
                if(!endedAt.equals("null"))
                {
                    endedAt = endedAt.substring(endedAt.indexOf("T") + 1, endedAt.lastIndexOf(":"));
                    isEnded=true;
                }
                else
                {
                    endedAt="ongoing";
                    isEnded=false;
                }
                item.timeDifference=createdAt+" - "+endedAt;
                if(externalSystem.equals("null"))
                {
                    item.externalSystem="";
                }
                else
                {
                    item.externalSystem = externalSystem;
                }
                Log.i("attr",externalSystem);
                items.add(item);

                itemAdapter=new ItemAdapter(getApplicationContext(), items);
                recyclerView.setAdapter(itemAdapter);
                if(isEnded) {
                error->    externalSystemView.setTextColor(Color.BLACK);
                }

The app is rather big, but I think you can get the idea from this piece of code.

Here is the error: Attempt to invoke virtual method 'void android.widget.TextView.setTextColor(int)' on a null object reference

public class ItemAdapter extends     
RecyclerView.Adapter<ItemAdapter.ItemViewHolder>{

private Context context;
private  ArrayList<Item> itemList;

public ItemAdapter(Context context, ArrayList<Item> itemList)
{
    this.context=context;
    this.itemList=itemList;
}

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

@Override
public void onBindViewHolder(ItemViewHolder holder, int position) {
    Item item=itemList.get(position);
    holder.timeDifference.setText(item.timeDifference);
    holder.title.setText(item.title);
    holder.timeCounter.setText(item.timeCounter);
    holder.externalSystem.setText(item.externalSystem);
    holder.type.setText(item.type);
    holder.project.setText(item.project);
    MY IDEA
    "holder.timeDifference.setTextColor(Color.parseColor(item.color));"
}

@Override
public int getItemCount() {
    if(itemList!=null)
        return itemList.size();
    else
        return 0;
}


    public static class ItemViewHolder extends RecyclerView.ViewHolder
{
    public CardView cardViewItem;
    public TextView title;
    public TextView project;
    public TextView externalSystem;
    public TextView timeDifference;
    public TextView timeCounter;
    public TextView type;

    public ItemViewHolder(View itemView)
    {
        super(itemView);
        cardViewItem=(CardView)itemView.findViewById(R.id.card_view_item);
        title=(TextView)itemView.findViewById(R.id.title);
        project=(TextView)itemView.findViewById(R.id.project);
        externalSystem=
        (TextView)itemView.findViewById(R.id.external_system);
        timeDifference=   
        (TextView)itemView.findViewById(R.id.time_difference);
        timeCounter=(TextView)itemView.findViewById(R.id.time_counter);
        type=(TextView)itemView.findViewById(R.id.type);
    }

EDIT: I think I found a way, but I don't know if it's the best one

4

1 に答える 1

1

Item解決策は、クラスを少し変更することです。

あなたの問題は、トリガーを適切に渡していないことbooleanです。たとえば、アイテムがどの状態にあるかを知るための の値。3 つのクラスすべてを使用する上で正しい考えがあります。RecyclerView.AdapterActivityisEndedBoolean

私がお勧めするのは、アダプターで使用されるItem値をクラスに渡すコンストラクターを作成することです。あなたのようにコードから直接変数を割り当てるよりも、Activity使いやすいと思いgettersます。setters

それでは始めましょう。

 boolean isEnded;
  if(!endedAt.equals("null")) {
     endedAt = endedAt.substring(endedAt.indexOf("T") + 1, endedAt.lastIndexOf(":"));
     isEnded=true;
  } else {
     endedAt="ongoing";
     isEnded=false;
  }
    String timeDifference = createdAt+" - "+endedAt;
  if(externalSystem.equals("null")) {
    externalSystem="";
  } else {
    externalSystem = externalSystem;
  }
    Log.i("attr",externalSystem);
    items.add(new ItemModel(isEnded, timeDifference, externalSystem);

    itemAdapter=new ItemAdapter(this, items);
    recyclerView.setAdapter(itemAdapter);
    itemAdapter.notifyDataSetChanged();

ItemModel内の変数の行ごとに new を配列に追加RecyclerViewし、その配列を に渡す方法に気付くでしょうAdapter。これは、どの変数がモデルに渡されているか、つまり 内の位置にある対応する行を簡単に把握できるようにするためAdapterです。

クラスの例は次のItemModelようになります。

public class ItemModel {
    // Getter and Setter model for recycler view items
    private boolean isEnded;
    private String timeDifference;
    private String externalSystem;
    //other variables, title etc etc 

    public ItemModel(boolean isEnded, String timeDifference, String externalSystem) {

        this.isEnded = isEnded;
        this.timeDifference = timeDifference;
        this.externalSystem = externalSystem;
        //only pass to the model if you can access it from code above  otherwise to assign the variables statically like you have.
    }

    public boolean getIsEnded() {return isEnded;}

    public String getTimeDifference() {return timeDifference;}

    public String getExternalSystem() { return externalSystem; }

}

上記の情報は、静的変数を使用するのではなく、データを渡すためのより効率的なモデル フレームワークを作成するための単なるガイドラインです。

問題を解決するには、その条件if (item.getIsEnded())に対応するテキストの色を確認してから変更する必要があります。if

RecyclerView.Adapter onBindViewHolder次のようになります。

@Override
public void onBindViewHolder(ItemViewHolder holder, int position) {
    ItemModel item =itemList.get(position);
    holder.timeDifference.setText(item.getTimeDifference());
    holder.title.setText(item.title);
    holder.timeCounter.setText(item.timeCounter);
    holder.externalSystem.setText(item.getExternalSystem());
    holder.type.setText(item.type);
    holder.project.setText(item.project);
    if (item.getIsEnded() {
    holder.timeDifference.setTextColor(item.color);
    } else {
    holder.timeDifference.setTextColor(item.color);
    }
}

の目的はAdapter、レイアウトを拡張し、コンポーネントをそのレイアウトにバインドし、専用の位置でレイアウトに対応するアイテムに機能を実行することです。Activityリスト内のどのアイテムがどの状態にあるかを知る必要があります。自分だけではそれを行うことはできません。の実際のアクティビティからコードを分離しAdapterておくことで、 がどれほど便利であるかに注意してください。ActivityRecyclerView

于 2017-01-12T14:56:24.383 に答える