0

I'm trying to get value from list.get(position).getPosition() and pass it to extras.putInt("STORY_POSITION", list.get(position).getPosition());, but the problem starts when I want to access value outside from method public void onDataChange(@NonNull DataSnapshot dataSnapshot). It throws me error: IndexOutOfBoundsException: Index: 0, Size: 0. So basically, I need a method, to get access to list values outside of onDataChange() method.

                final List<User> list = new ArrayList<>();
                holder.cont.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    rootRef.child("users").child(mAuth.getUid()).addValueEventListener(new ValueEventListener() {
                        @Override
                        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                            for (DataSnapshot ds: dataSnapshot.getChildren()){
                                user = ds.getValue(User.class);
                                list.add(user);
                            }                             
                        }

                        @Override
                        public void onCancelled(@NonNull DatabaseError databaseError) { }
                    });

                    Intent intent = new Intent(getApplicationContext(), StoryActivity.class);
                    Bundle extras = new Bundle();
                    extras.putInt("PROJECT_ID", position);
                    extras.putInt("STORY_POSITION", list.get(position).getPosition());
                    extras.putInt("STORY_ID", model.getPosition_on_tree());
                    extras.putInt("CHAPTER_SIZE", model.getChapter_size());
                    intent.putExtras(extras);
                    startActivity(intent);
                    finish();
                }
            });

EDIT: The reason I need to get list.get(position).getPosition() outside of onDataChange method is that I have another method where calling onStop I pass new position value to DB, and automatically when the MainActivity starts, it closes and opens StoryActivity because value has changed in DB. It also happens inside MainActivity when I manually override values in DB.This is the link to my MainActivity code and link to StoryActivity.

Mārtiņš Ciekurs
  • 437
  • 1
  • 6
  • 25
  • I have answered this question here https://stackoverflow.com/a/55741593/3904109 please have a look it will help you... – DragonFire Apr 18 '19 at 08:14

2 Answers2

2

Its a simple trick, you can use a Handler and check list data before post-runnable.

     final List<User> list = new ArrayList<>();
            holder.cont.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                rootRef.child("users").child(mAuth.getUid()).addValueEventListener(new ValueEventListener() {
                    @Override
                    public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                        for (DataSnapshot ds: dataSnapshot.getChildren()){
                            user = ds.getValue(User.class);
                            list.add(user);
                        }                             
                    }

                    @Override
                    public void onCancelled(@NonNull DatabaseError databaseError) { }
                });
             Handler handler = new Handler();
             int delay = 1000; //milliseconds

             handler.postDelayed(new Runnable(){
                 public void run(){
                     if(!list.isEmpty())//checking if the data is loaded or not
                    {
                          Intent intent = new Intent(getApplicationContext(), StoryActivity.class);
                          Bundle extras = new Bundle();
                          extras.putInt("PROJECT_ID", position);
                          extras.putInt("STORY_POSITION", 
                          list.get(position).getPosition());
                          extras.putInt("STORY_ID", model.getPosition_on_tree());
                          extras.putInt("CHAPTER_SIZE", model.getChapter_size());
                          intent.putExtras(extras);
                          startActivity(intent);
                          finish();
                    }
                     else
                         handler.postDelayed(this, delay);
                 }
             }, delay);
           }
        });

The code will only execute when the data is fetched from firebase.

abdul rehman
  • 250
  • 2
  • 8
0

onDataChange is an asynchronous call which will be executed at some other point of time. It will be not be executed sequentially as a result you are experiencing the issue.

Update your code as follows:

public void onClick(View v) {
    rootRef.child("users").child(mAuth.getUid()).addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            for (DataSnapshot ds: dataSnapshot.getChildren()){
                user = ds.getValue(User.class);
                list.add(user);
            }        
            Intent intent = new Intent(getApplicationContext(), StoryActivity.class);
            Bundle extras = new Bundle();
            extras.putInt("PROJECT_ID", position);
            extras.putInt("STORY_POSITION", list.get(position).getPosition());
            extras.putInt("STORY_ID", model.getPosition_on_tree());
            extras.putInt("CHAPTER_SIZE", model.getChapter_size());
            intent.putExtras(extras);
            startActivity(intent);
            finish();                 
       }

       @Override
       public void onCancelled(@NonNull DatabaseError databaseError) { }
  });
}
Sagar
  • 23,903
  • 4
  • 62
  • 62
  • I updated my question to clarify where exactly is my problem – Mārtiņš Ciekurs Jun 04 '18 at 10:22
  • @MārtiņšCiekurs What ever you are doing outside of `onDataChange` why can't you do it inside? – Sagar Jun 04 '18 at 10:24
  • Because if I add `startActivity` inside `onDataChange` method, it automatically starts second activity. I want that I only works when I press `cont` button – Mārtiņš Ciekurs Jun 04 '18 at 10:27
  • @MārtiņšCiekurs Then put all your code related to `Intent intent = new Intent(getApplicationContext(), StoryActivity.class);` in `cont` onClick. Putting it outside won't help you to achieve your intended behavior since the call is asynchronous. – Sagar Jun 04 '18 at 10:29
  • But the problem is that I have already tried it inside `cont` onClick, and it anyways calls `startActivity` when data has been changed and also when I go from StoryActivity to MainActivity – Mārtiņš Ciekurs Jun 04 '18 at 10:31
  • @MārtiņšCiekurs what is your intention? Do don't want it to be called if data has changed? – Sagar Jun 04 '18 at 10:37
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/172394/discussion-between-mrtis-ciekurs-and-sagar). – Mārtiņš Ciekurs Jun 04 '18 at 10:38