0

I have a Room database, containing a list of members. There are different members in a list. I want to click on a specific member and then it should start a new activity where I can see additional information about that member. But when I click on a member, the app crashes.

Code of my adapter:

public class MemberListAdapter extends RecyclerView.Adapter<MemberListAdapter.MemberViewHolder> {

    private List<Member> mMember;
    private MemberClickListener listener;


    public interface MemberClickListener {
        void onMemberClick(int position);
    }

    public MemberListAdapter(final MemberClickListener listener) {
        this.listener = listener;
    }


    @Override
    public MemberViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_member, parent, false);
        return new MemberViewHolder(itemView, listener);
    }


    void setMember(List<Member> members) {
        mMember = members;
        notifyDataSetChanged();
    }

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


    @Override
    public void onBindViewHolder(MemberViewHolder holder, int position) {
        holder.bind(mMember.get(position), listener);
    }

    class MemberViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

        private final MemberClickListener listener;
        private final TextView firstname;
        private final TextView surname;
        private final TextView balance;

        MemberViewHolder(View itemView, MemberClickListener listener) {
            super(itemView);
            firstname = itemView.findViewById(R.id.layout_firstname);
            surname = itemView.findViewById(R.id.layout_surname);
            balance = itemView.findViewById(R.id.layout_balance);
            this.listener = listener;

            itemView.setOnClickListener(this);
        }


        public void bind(final Member member, final MemberClickListener listener) {
            firstname.setText(member.getFirstname());
            surname.setText(member.getSurname());
            //balance.setText(toString(member.getBalance()));

            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Log.i("test1", "beforelistenercheck");
                    if (listener != null) {
                        Log.i("test2", "duringlistenercheck");
                        listener.onMemberClick(getAdapterPosition());
                        Log.i("test3", "aftergettingposition");
                    }
                }
            });
        }

        public void onClick(View v) {
            if (listener != null) {
                ********listener.onMemberClick(getAdapterPosition());********
            }
        }
    }
}

Code of my main activity:

public class MemberMainActivity extends AppCompatActivity implements MemberListAdapter.MemberClickListener{

    private MemberViewModel mMemberViewModel;
    private List<Member> mMember;

    void setMember(List<Member> members) {
        mMember = members;
    }

    public static final int NEW_MEMBER_ACTIVITY_REQUEST_CODE = 1;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_member);
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        FloatingActionButton fab = findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(MemberMainActivity.this, NewMemberActivity.class);
                startActivityForResult(intent, NEW_MEMBER_ACTIVITY_REQUEST_CODE);
            }
        });

        RecyclerView recyclerView = findViewById(R.id.recyclerviewcard_member);
        final MemberListAdapter adapter = new MemberListAdapter(this);
        recyclerView.setAdapter(adapter);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));

        mMemberViewModel = ViewModelProviders.of(this).get(MemberViewModel.class);

        mMemberViewModel.getAllMember().observe(this, new Observer<List<Member>>() {
            @Override
            public void onChanged(@Nullable final List<Member> members) {
                // Update the cached copy of the words in the adapter.
                adapter.setMember(members);
            }
        });
    }

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == NEW_MEMBER_ACTIVITY_REQUEST_CODE && resultCode == RESULT_OK) {
            Member member = new Member(data.getStringExtra(NewMemberActivity.EXTRA_REPLY), data.getStringExtra(NewMemberActivity.EXTRA_REPLY2));
            mMemberViewModel.insert(member);
        } else {
            Toast.makeText(
                    getApplicationContext(),
                    R.string.empty_not_saved,
                    Toast.LENGTH_LONG).show();
        }
    }


    public void onMemberClick(int position) {
        **********Member member = mMember.get(position);**********
        MemberInfo.open(this, member.getId());
    }
}

Code of the activity which should be launched after clicking on a member:

public class MemberInfo extends AppCompatActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_memberinfo);

        Intent intent = getIntent();
        if (intent != null && intent.hasExtra("MemberID")) {
            long memberid = intent.getLongExtra("MemberID", -1);
            // TODO: get customer details based on customer id
            Bundle bundle = new Bundle();
            bundle.putLong("MemberID", memberid);
            intent.putExtras(bundle);
            startActivity(intent);
        }
        else {
            Toast.makeText(
                    getApplicationContext(),
                    R.string.empty_not_saved,
                    Toast.LENGTH_LONG).show();
        }
    }

    public static void open(Activity activity, long memberid) {
        Intent intent = new Intent(activity, MemberInfo.class);
        intent.putExtra("MemberID", memberid);
        activity.startActivity(intent);
    }
}

The error:

logcat: java.lang.NullPointerException: Attempt to invoke interface method 'java.lang.Object java.util.List.get(int)' on a null object reference
        at com.example.ahash.mainbuchhaltung.Member.MemberMainActivity.onMemberClick(MemberMainActivity.java:81)
        at com.example.ahash.mainbuchhaltung.Member.MemberListAdapter$MemberViewHolder$1.onClick(MemberListAdapter.java:86)
        at android.view.View.performClick(View.java:6256)
        at android.view.View$PerformClick.run(View.java:24701)
        at android.os.Handler.handleCallback(Handler.java:789)
        at android.os.Handler.dispatchMessage(Handler.java:98)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6541)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

I marked the lines, where the error is, with stars. I also tried to solve my problem with the answers to this question: What is a NullPointerException, and how do I fix it?

I have three different Logs in my adapter code, named "test1", "test2" and "test3". I emulated my app and "test1" and "test2" were shown in my logcat, but "test3" wasn't shown.

I have been working on this for three weeks, and I'm still standing at the same problem as before. Can anyone help me to solve this problem?

SedJ601
  • 12,173
  • 3
  • 41
  • 59
LordGash
  • 285
  • 1
  • 4
  • 14

3 Answers3

1

your mMember is null inside the onMemberClick method.

Eury Pérez Beltré
  • 2,017
  • 20
  • 28
  • Do you mean in the adapter code or in the activity code? If it's wrong in the activity code, what should I do? Write this line: private List members? – LordGash Jun 13 '18 at 20:36
  • You have either to initialize the mMember list or check for nulity in the `onMemberClick()` method. – Eury Pérez Beltré Jun 13 '18 at 20:39
  • If you mean it in the code for main activity, I tried this:public void onMemberClick(int position) {setMember(mMembers) **********Member member = mMember.get(position);********** MemberInfo.open(this, member.getId()); } – LordGash Jun 13 '18 at 20:46
  • I also tested this: public void onMemberClick(int position) {if(position>0){ **********Member member = mMember.get(position);********** MemberInfo.open(this, member.getId()); } } – LordGash Jun 13 '18 at 20:47
  • Both of them didn't work. Can you look if my adapter is coded correctly? The part where I have my logs? Because in my logcat, I can see test1 and test2, but NO test3. – LordGash Jun 13 '18 at 20:48
  • Try this: In the `onChanged` method before the `adapter.setMember(members);` do `mMembers = members;` and leave the code inside the `onMemberClick` like the original. – Eury Pérez Beltré Jun 13 '18 at 21:05
  • So now I see all three tests in my logcat, but now this error shows up: /com.example.mainbuchhaltung E/gralloc_ranchu: map_buffer: failed to map ashmem region! gralloc_register_buffer(0xb1a7980): map failed: Out of memory com.example.mainbuchhaltung W/GraphicBufferMapper: importBuffer(0x89bd49a0) failed: 2 com.example.mainbuchhaltung E/GraphicBuffer: unflatten: registerBuffer failed: Unknown error -2 (2) – LordGash Jun 13 '18 at 21:12
  • com.example.mainbuchhaltung E/Surface: dequeueBuffer: IGraphicBufferProducer::requestBuffer failed: 2 com.example.mainbuchhaltung E/EGL_emulation: tid 7340: init(382): error 0x3003 (EGL_BAD_ALLOC) tid 7340: eglCreateWindowSurface(922): error 0x3003 (EGL_BAD_ALLOC) /com.example.mainbuchhaltung A/OpenGLRenderer: Failed to create EGLSurface for window 0x27f808, eglErr = EGL_BAD_ALLOC com.example.mainbuchhaltung A/libc: Fatal signal 6 (SIGABRT), code -6 in tid 7340 (RenderThread) – LordGash Jun 13 '18 at 21:12
  • Does the error happen just because my emulator doesn't have full access on the computer's memory? – LordGash Jun 13 '18 at 21:12
  • I noticed something new. I tried different logs, also in the onMemberClick method, and it showed me the log in my logcat. But then I put a log in the activity which should be started after a member got clicked. I put the code in the onCreate method after setContentView. So, when I click on a member, it loads and loads non-stop. I look into the logcat and just see the same log repeatedly, which I put after setContentView. Do you maybe know why that could happen? – LordGash Jun 13 '18 at 21:31
1

I have created a new project using your code, and you forgot to initialize your list of member called "mMember".

I created a method to load fake members and everything is working without problems.

Example:

private void loadFakeData(){
        mMember = new ArrayList<>();
        Member newMember;
        for (int i = 0; i < 10; i++) {
            newMember = new Member();
            newMember.setFirstName("Firstname " + i);
            newMember.setSurName("Surname " + i);

            mMember.add(newMember);
        }
        mAdapter.setMember(mMember);
    }
Juanjo Berenguer
  • 789
  • 1
  • 5
  • 8
0

Your private List<Member> mMember in your main activity is not initialized when you acess it (most likely in the listener).

You could make it private List<Member> mMember = new ArrayList<Member(); instead and have at least an empty list.

As an alternative, you could insert mMember = new ArrayList<Member>(); somewhere before mMemberViewModel.getAllMember().observe(this, new Observer<List<Member>>() in onCreate().

deHaar
  • 17,687
  • 10
  • 38
  • 51
  • I thought that is the list from the database which I set with a getter method. I just tried your solution, but it shows me this: List is abstract, cannot be instantiated. – LordGash Jun 13 '18 at 20:34
  • I have this error when I try: java.lang.IndexOutOfBoundsException: Index: 1, Size: 0 – LordGash Jun 13 '18 at 20:40
  • Well, that is a different problem now... The list is empty, but somewhere in your code the index 1 gets accessed. That causes an `IndexOutOfBoundsException`. Index 1 does not exist when size is 0... – deHaar Jun 13 '18 at 20:43
  • Whow, so what do I have to do? Sorry for asking so much, I'm still new to programming. – LordGash Jun 13 '18 at 20:49
  • You have to find the line of code where an access to a not existing index might happen. If you know how to use a debugger, use it. Otherwise you could start logging some values like size of the list and any numeric value that might be used as index when accessing the list. – deHaar Jun 13 '18 at 20:52