Search code examples
androidarraysandroid-layoutlistviewandroid-arrayadapter

Array of Widgets(TextView,RelativeLayout etc) causing Null Pointer Exception


I am reposting this question as one person marked my previous queston duplicate even without reading the question.

I am creating a adapter of ListView, for loading my custom layout as list members.

The layout contains

  • 3 RelativeLayout

  • and each of the latter contains a TextView

  • and a Button.

    In the ListView there will be at max 2 rows, in short at max 6 RelativeLayout. As the need is recursive I have used array of TextView,RelativeLayout,Button. For assigning Id through findViewById(), I am using int array which contains all ids defined in layout. Now after I assign the widgets their Id, when I am invoking any method it is giving null pointer exception, which mean that the widget is not assigned Id but I cannot understand why it is not assigned.

One more point that the ListView is populated within an RecyclerView.Adapter. The whole scene is like this:

i) I have a activity with Tabs & Pager. Hence it uses fragments for each tab. Here I am talking about first tab only.

ii) In the fragment I have a RecyclerView which will load cards.

iii) The card has many widget, one of them is ListView. So In RecyclerView.Adapter I will call the ArrayAdapter for this List

My code is as follow:

1) ArrayAdapter (which shows error)

public class ElectionOptionAdapter extends ArrayAdapter<String> {

    Activity context;
    int noOption;
    String[] options, description;
    TextView[] optionText, optionDescription;
    RelativeLayout[] optionImage;
    Button[] optionButton;

    int[]
    text = new int[]{R.id.ERowOption1,R.id.ERowOption2,R.id.ERowOption3},
    des = new int[]{R.id.ERowOption1des,R.id.ERowOption2des,R.id.ERowOption3des},
    img = new int[]{R.id.ERowOption1Img,R.id.ERowOption2Img,R.id.ERowOption3Img},
    but = new int[]{R.id.ERowOption1button,R.id.ERowOption2button,R.id.ERowOption3button};
    public ElectionOptionAdapter(Activity context, int length, String[] options, String[] description) {

        super(context, R.layout.election_type_options,options);
        this.context = context;
        this.options = options;
        this.description = description;

        noOption=options.length;
        optionText = new TextView[noOption];
        optionDescription = new TextView[noOption];
        optionImage = new RelativeLayout[noOption];
        optionButton = new Button[noOption];

    }

    @Override
    public int getCount() {
        return 1;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {


        LayoutInflater inflater = context.getLayoutInflater();
        View card = inflater.inflate(R.layout.election_type_options, parent, false);

        for (int i = 1+(3*position); i <= Math.min(3+(3*position),options.length); i++) {
            optionText[i-1] = (TextView) card.findViewById(text[(i%4)-1]);
            optionDescription[i-1] = (TextView) card.findViewById(des[(i%4)-1]);
            optionImage[i-1] = (RelativeLayout) card.findViewById(img[(i%4)-1]);
            optionButton[i-1] = (Button) card.findViewById(but[(i%4)-1]);

            //The error message points here
            optionImage[i-1].setVisibility(View.VISIBLE);
            optionText[i-1].setText(options[i-1]);
            optionDescription[i-1].setText(description[i-1]);
        }

        optionButton[0].setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                visibilityChange(0);
            }
        });
        optionButton[1].setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                visibilityChange(1);
            }
        });
        optionButton[2].setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                visibilityChange(2);
            }
        });
        optionButton[3].setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                visibilityChange(3);
            }
        });
        optionButton[4].setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                visibilityChange(4);
            }
        });
        optionButton[5].setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                visibilityChange(5);
            }
        });

        return card;
    }

    private void visibilityChange(int pos){
        if(optionDescription[pos].getVisibility()==View.VISIBLE)
            optionDescription[pos].setVisibility(View.INVISIBLE);
        else
            optionDescription[pos].setVisibility(View.VISIBLE);
    }

}

2) The Error Message:

       java.lang.NullPointerException: 
    Attempt to invoke virtual method 'void android.widget.RelativeLayout.setVisibility(int)' 
on a null object reference at com.package.ElectionOptionAdapter.getView(ElectionOptionAdapter.java:72)

3) The Layout File :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    android:paddingBottom="5dp"
    android:paddingTop="5dp">

    <RelativeLayout
        android:tag="@+id/ERowOption1Img"
        android:layout_width="120dp"
        android:layout_height="120dp"
        android:layout_marginLeft="2dp"
        android:layout_marginRight="4dp"
        android:visibility="invisible">

        <TextView
            android:tag="@+id/ERowOption1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:minHeight="25dp"
            android:textStyle="bold"
            android:text=" A) Gaurav Jindal"
            android:layout_alignParentBottom="true" />
        <TextView
            android:background="#FFFFFF"
            android:tag="@+id/ERowOption1des"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:visibility="invisible"/>

        <Button
            android:tag="@+id/ERowOption1button"
            android:layout_width="20dp"
            android:layout_height="20dp"
            android:layout_alignParentTop="true"
            android:layout_alignParentRight="true"
            android:background="@drawable/info_election_option"/>
    </RelativeLayout>

    <RelativeLayout
        android:tag="@+id/ERowOption2Img"
        android:layout_width="120dp"
        android:layout_height="120dp"
        android:layout_marginLeft="2dp"
        android:layout_marginRight="4dp"
        android:visibility="invisible">

        <TextView
            android:tag="@+id/ERowOption2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:minHeight="25dp"
            android:textStyle="bold"
            android:text=" A) Gaurav Jindal"
            android:layout_alignParentBottom="true" />
        <TextView
            android:tag="@+id/ERowOption2des"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:visibility="invisible"/>

        <Button
            android:tag="@+id/ERowOption2button"
            android:layout_width="20dp"
            android:layout_height="20dp"
            android:layout_alignParentTop="true"
            android:layout_alignParentRight="true"
            android:background="@drawable/info_election_option"/>
    </RelativeLayout>

    <RelativeLayout
        android:tag="@+id/ERowOption3Img"
        android:layout_width="120dp"
        android:layout_height="120dp"
        android:layout_marginLeft="2dp"
        android:layout_marginRight="4dp"
        android:visibility="invisible">

        <TextView
            android:tag="@+id/ERowOption3"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:minHeight="25dp"
            android:textStyle="bold"
            android:text=" A) Gaurav Jindal"
            android:layout_alignParentBottom="true" />
        <TextView
            android:tag="@+id/ERowOption3des"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:visibility="invisible"/>

        <Button
            android:tag="@+id/ERowOption3button"
            android:layout_width="20dp"
            android:layout_height="20dp"
            android:layout_alignParentTop="true"
            android:layout_alignParentRight="true"
            android:background="@drawable/info_election_option"/>
    </RelativeLayout>   
</LinearLayout>

4) The RecyclerAdapter which calls ListAdapter mentioned above is:

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

    JSONArray jsonArray;
    Activity context;

    public static class ViewHolder extends RecyclerView.ViewHolder {
        TextView userid,question;
        ImageView userdp;
        ListView optionList;

        public ViewHolder(View card) {
            super(card);
            userid = (TextView) card.findViewById(R.id.useridInCard);
            question = (TextView) card.findViewById(R.id.questionInCard);
            optionList = (ListView) card.findViewById(R.id.optionInCard);
        }
    }

    FeedAdapter(Activity context,JSONArray jsonArray){
        this.context=context;
        this.jsonArray = jsonArray;
    }

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

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        try {
            JSONObject currentFeed = jsonArray.getJSONObject(position);

            holder.userid.setText(currentFeed.getString("_id"));
            holder.question.setText(currentFeed.getString("Question"));
            int noOptions = currentFeed.getInt("noOption");
            String[] option = new String[noOptions];
            for(int i=1;i<=noOptions;i++)
                option[i-1]=optionName(i)+currentFeed.getString("Option"+i);

           String[] description = new String[noOptions];
           for(int i=1;i<=noOptions;i++)
               description[i-1]=currentFeed.getString("Description"+i);
           ElectionOptionAdapter electionAdapter;
                if(noOptions<=3)
                    electionAdapter= new ElectionOptionAdapter(context,1,option,description);
                else
                    electionAdapter= new ElectionOptionAdapter(context,2,option,description);

                holder.optionList.setAdapter(electionAdapter);


        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public int getItemCount() {
        return 1;
    }
}

Solution

  • In the Layout's xml file you should be using the attribute

    android:id="@+id/foobar"
    

    instead of

    android:tag="@+id/foobar"