3

How to handle the problem of showing empty view for ListView because I don't know which data I have to put when I'm reading data from my firebase DB and display it in the ListView. and I'm using CustomListAdapter to change font color and the background color of ListView

Note: I'm reading data from firebase database and display it in ListView, any solution

CustomListAdapter.java

   public class CustomListAdapter extends BaseAdapter {

private static final int HERO_COUNT = 12;
private Context context;
private List<String> items;

public CustomListAdapter(Context context) {
    this.context = context;
    items = new ArrayList<>();
}

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

@Override
public String getItem(int position) {
    if (position >= 0 && position < items.size()) {
        return items.get(position);
    }
    return "";
}

@Override
public long getItemId(int position) {
    return 0;
}

@Override
public View getView(int position, View v, ViewGroup parent) {
    View mView = v;
    if (mView == null) {
        LayoutInflater vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        mView = vi.inflate(R.layout.custom_list, null, false);

        TextView text = (TextView) mView.findViewById(R.id.textView);
        //textView.setTextColor(Color.BLUE);
        text.setText(getItem(position));
        if (items.isEmpty()) {
            // Set holder color
        } else {
            text.setTextColor(Color.WHITE);
            int color = Color.argb(200, 255, 64, 64);
            text.setBackgroundColor(color);
        }


    }

    return mView;
}

public void updateList(List<String> updatedItems) {
    items.clear();
    items.addAll(updatedItems);
    notifyDataSetChanged();
}
}

ViewDatabase.java

public class ViewDatabase extends AppCompatActivity {
private static final String TAG = "ViewDatabase";

//add Firebase Database stuff
private FirebaseDatabase mFirebaseDatabase;
private FirebaseAuth mAuth;
private FirebaseAuth.AuthStateListener mAuthListener;
private DatabaseReference myRef;
private String userID;

private ListView mListView;


@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.view_database_layout);

    mListView = (ListView) findViewById(R.id.listview);
    CustomListAdapter adapter = new CustomListAdapter(this);
    mListView.setAdapter(adapter);


    //declare the database reference object. This is what we use to access the database.
    //NOTE: Unless you are signed in, this will not be useable.
    mAuth = FirebaseAuth.getInstance();
    mFirebaseDatabase = FirebaseDatabase.getInstance();
    myRef = mFirebaseDatabase.getReference();
    FirebaseUser user = mAuth.getCurrentUser();
    // userID = user.getUid();
    userID = "";

    mAuthListener = new FirebaseAuth.AuthStateListener() {
        @Override
        public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
            FirebaseUser user = firebaseAuth.getCurrentUser();
            if (user != null) {
                // User is signed in
                Log.d(TAG, "onAuthStateChanged:signed_in:" + user.getUid());
                toastMessage("Successfully signed in.");
            } else {
                // User is signed out
                Log.d(TAG, "onAuthStateChanged:signed_out");
                toastMessage("Successfully signed out.");
            }
            // ...
        }
    };

    myRef.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            // This method is called once with the initial value and again
            // whenever data at this location is updated.
            showData(dataSnapshot);
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });

}


private void showData(DataSnapshot dataSnapshot) {
    for (DataSnapshot ds : dataSnapshot.getChildren()) {
        DailyInfo uInfo = new DailyInfo();
        uInfo.setHero1(ds.child(userID).getValue(DailyInfo.class).getHero1()); //set the name1
        uInfo.setHero2(ds.child(userID).getValue(DailyInfo.class).getHero2()); //set the name2
        uInfo.setHero3(ds.child(userID).getValue(DailyInfo.class).getHero3()); //set the name3
        uInfo.setHero4(ds.child(userID).getValue(DailyInfo.class).getHero4()); //set the name4
        uInfo.setHero5(ds.child(userID).getValue(DailyInfo.class).getHero5()); //set the name5
        uInfo.setHero6(ds.child(userID).getValue(DailyInfo.class).getHero6()); //set the name6
        uInfo.setHero7(ds.child(userID).getValue(DailyInfo.class).getHero7()); //set the name7
        uInfo.setHero8(ds.child(userID).getValue(DailyInfo.class).getHero8()); //set the name8
        uInfo.setHero9(ds.child(userID).getValue(DailyInfo.class).getHero9()); //set the name9
        uInfo.setHero10(ds.child(userID).getValue(DailyInfo.class).getHero10()); //set the name10
        uInfo.setHero11(ds.child(userID).getValue(DailyInfo.class).getHero11()); //set the name11
        uInfo.setHero12(ds.child(userID).getValue(DailyInfo.class).getHero12()); //set the name12


        //display all the information
        Log.d(TAG, "showData: Hero1: " + uInfo.getHero1());
        Log.d(TAG, "showData: Hero2: " + uInfo.getHero2());
        Log.d(TAG, "showData: Hero3: " + uInfo.getHero3());
        Log.d(TAG, "showData: Hero4: " + uInfo.getHero4());
        Log.d(TAG, "showData: Hero5: " + uInfo.getHero5());
        Log.d(TAG, "showData: Hero6: " + uInfo.getHero6());
        Log.d(TAG, "showData: Hero7: " + uInfo.getHero7());
        Log.d(TAG, "showData: Hero8: " + uInfo.getHero8());
        Log.d(TAG, "showData: Hero9: " + uInfo.getHero9());
        Log.d(TAG, "showData: Hero10: " + uInfo.getHero10());
        Log.d(TAG, "showData: Hero11: " + uInfo.getHero11());
        Log.d(TAG, "showData: Hero12: " + uInfo.getHero12());


        ArrayList<String> array = new ArrayList<>();
        array.add(uInfo.getHero1());
        array.add(uInfo.getHero2());
        array.add(uInfo.getHero3());
        array.add(uInfo.getHero4());
        array.add(uInfo.getHero5());
        array.add(uInfo.getHero6());
        array.add(uInfo.getHero7());
        array.add(uInfo.getHero8());
        array.add(uInfo.getHero9());
        array.add(uInfo.getHero10());
        array.add(uInfo.getHero11());
        array.add(uInfo.getHero12());

     /*   ArrayAdapter adapter = new ArrayAdapter(this,android.R.layout.simple_list_item_1,array);
        mListView.setAdapter(adapter);*/

        if (mListView.getAdapter() instanceof CustomListAdapter) {
            ((CustomListAdapter) mListView.getAdapter()).updateList(array);
            mListView.setBackgroundColor(ContextCompat.getColor(mListView.getContext(), R.color.category_colors));
        }
    }

}

@Override
public void onStart() {
    super.onStart();
    mAuth.addAuthStateListener(mAuthListener);
}

@Override
public void onStop() {
    super.onStop();
    if (mAuthListener != null) {
        mAuth.removeAuthStateListener(mAuthListener);
    }
}


/**
 * customizable toast
 *
 * @param message
 */
private void toastMessage(String message) {
    Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
}

view_database_layout.xml

<?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="vertical">

 <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

 <TextView
    android:id="@+id/tvUserInfo"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="User Information"
    android:textAlignment="center"
    android:textColor="@color/colorPrimaryDark"
    android:textSize="25sp"/>

<ListView
    android:id="@+id/listview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

</LinearLayout>

</LinearLayout>

custom_list.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:id="@+id/textView"
    android:textSize="20px" android:paddingTop="10dip" android:paddingBottom="10dip"/>
</LinearLayout>

DailyInfo.java

public class DailyInfo {

private String hero1;

private String hero2;
private String hero3;
private String hero4;
private String hero5;
private String hero6;
private String hero7;
private String hero8;
private String hero9;
private String hero10;
private String hero11;
private String hero12;



public DailyInfo(){

}


public String getHero1() {
    return hero1;
}

public void setHero1(String hero1) {
    this.hero1 = hero1;
}


public String getHero2() {
 return hero2;
 }

public void setHero2(String hero2) {
    this.hero2 = hero2;
}

public String getHero3() {
    return hero3;
}

public void setHero3(String hero3) {
    this.hero3 = hero3;
}

public String getHero4() {
    return hero4;
}

public void setHero4(String hero4) {
    this.hero4 = hero4;
}

public String getHero5() {
    return hero5;
}

public void setHero5(String hero5) {
    this.hero5 = hero5;
}

public String getHero6() {
    return hero6;
}

public void setHero6(String hero6) {
    this.hero6 = hero6;
}

public String getHero7() {
    return hero7;
}

public void setHero7(String hero7) {
    this.hero7 = hero7;
}

public String getHero8() {
    return hero8;
}

public void setHero8(String hero8) {
    this.hero8 = hero8;
}

public String getHero9() {
    return hero9;
}

public void setHero9(String hero9) {
    this.hero9 = hero9;
}

public String getHero10() {
    return hero10;
}

public void setHero10(String hero10) {
    this.hero10 = hero10;
}

public String getHero11() {
    return hero11;
}

public void setHero11(String hero11) {
    this.hero11 = hero11;
}

public String getHero12() {
    return hero12;
}

public void setHero12(String hero12) {
    this.hero12 = hero12;
}
}
MB_Coder
  • 765
  • 1
  • 7
  • 14

2 Answers2

2

You're creating the adapter after receiving the response on ValueEventListener:

    CustomListAdapter adapter = new CustomListAdapter(ViewDatabase.this , R.layout.custom_list , mList);
    ListView mListView= findViewById(R.id.listview);
    mListView.setAdapter(adapter);

Instead of that, set the adapter on ViewDatabase within onCreate for instance and set the color based on that initial state.

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.view_database_layout);

        mListView = findViewById(R.id.listview);
        CustomListAdapter adapter = new CustomListAdapter(this);
        mListView.setAdapter(adapter);

        //[...]
    }

And, instead of creating the adapter, update it:

    private void showData(DataSnapshot dataSnapshot) {

        //[...]

        if (mListView.getAdapter() instanceof CustomListAdapter) {
            ((CustomListAdapter)mListView.getAdapter()).updateList(array);
        }
    } 

You could also replace ArrayAdapter with BaseAdapter as the extended class:

    public class CustomListAdapter extends BaseAdapter {

        private static final int HERO_COUNT = 12;
        private Context context;
        private List<String> items;

        public CustomListAdapter(Context context) {
            this.context = context;
            items = new ArrayList<>();
        }

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

        @Override
        public String getItem(int position) {
            if (position >= 0 && position < items.size()) {
                return items.get(position);
            }
            return "";
        }

        @Override
        public long getItemId(int position) {
            return 0;
        }

        @Override
        public View getView(int position, View v, ViewGroup parent) {
            View mView = v;
            if (mView == null) {
                LayoutInflater vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                mView = vi.inflate(R.layout.custom_list, null, false);
            }
            //Bind view content here
            //TODO associate holder to tag
            return mView;
        }

        public void updateList(List<String> updatedItems) {
            items.clear();
            items.addAll(updatedItems);
            notifyDataSetChanged();
        }
    }
}

EDIT:

In order to have a default background color on the list to be changed when the values are received, you can set the default color on the main layout:

<?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="vertical">

 <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

 <TextView
    android:id="@+id/tvUserInfo"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="User Information"
    android:textAlignment="center"
    android:textColor="@color/colorPrimaryDark"
    android:textSize="25sp"/>

<ListView
    android:id="@+id/listview"
    android:background="@color/empty_color"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

</LinearLayout>

</LinearLayout>

And then change it when the values are received:

    private void showData(DataSnapshot dataSnapshot) {

        //[...]

        if (mListView.getAdapter() instanceof CustomListAdapter) {
            ((CustomListAdapter)mListView.getAdapter()).updateList(array);
            listView.setBackgroundColor(ContextCompat.getColor(listView.getContext(), R.color.loaded_color));
        }
    } 

If what you want is to change the row color then you'll need to change the row layout on getView when the string is empty.

EDIT 2 Specified where to make the view changes

randomuser
  • 603
  • 4
  • 16
  • thank you @randomuser for your answer, Actually, I change my 'CustomListAdapter', with 'BaseAdapter' like your code but first, set the adapter on'ViewDatabase' ask me to change the signature of 'CustomListAdapter'(Context,int,List) and I did it, second please can you show me how to do instance within 'onCreate' with an array of empty starting and set the colour based on that, thank you again – MB_Coder Jun 09 '18 at 15:57
  • please can you show me how to do instance within `onCreate` with an array of empty starting and set the color based on that, thank you @randomuser – MB_Coder Jun 09 '18 at 17:34
  • I updated my question and I'm trying to set the color inside mList like this mList.add(String.valueOf(ContextCompat.getColor(ViewDatabase.this, R.color.colorPrimary))); but it's not working @randomuser – MB_Coder Jun 09 '18 at 19:49
  • Why would you do `mList.add(String.valueOf(ContextCompat.getColor(ViewDatabase.this, R.color.colorPrimary)))`? – randomuser Jun 09 '18 at 19:53
  • Now I updated my question like your code but it shows `NPE` and I updated my question with my `logcat`, can you check it, please? @randomuser – MB_Coder Jun 09 '18 at 20:43
  • You're never setting your mList, always null, therefore the NullPointerException – randomuser Jun 09 '18 at 23:25
  • please, can you show me how to set the color value to mList, because it's not working for me, any help @randomuser – MB_Coder Jun 10 '18 at 21:29
  • An additional vote would be appreciated, but you can add a background based on the state, although that defeats the purpose of a custom adapter to set up the row color – randomuser Jun 11 '18 at 03:28
  • I really appreciate it for your help, actually, I'm adding CustomListAdapter to change the View color of font and the background for data inside my firebase because of I read the data from my firebase database – MB_Coder Jun 11 '18 at 03:39
  • for `mList` i don't know how to fix it because only I need to pass color with my data came from firebase database – MB_Coder Jun 11 '18 at 03:43
  • thank you so much, sir now it's working but without display any data, I think it's missing to connect DailyInfo class inside my CustomListAdapter to convert custom_list layout with my main layout @randomuser – MB_Coder Jun 12 '18 at 01:50
  • please, can you check my CustomListAdapter and DailyInfo class if you have a time @randomuser – MB_Coder Jun 12 '18 at 01:53
  • Seems from your edition changes you deleted the code from getView to set the text – randomuser Jun 12 '18 at 04:58
  • please can you help me for that to set the text inside setView @randomuser – MB_Coder Jun 12 '18 at 13:13
  • Check the history of your post, you had it already and just copy pasted my answer, that only highlighted your question about the background, without even having a look – randomuser Jun 12 '18 at 14:42
  • sir, I updated my question with the old edition on the `getView` method but still doesn't display the data and I think the problem inside the Override method `getItem` because it's not connected to `DailyInfo` class, any help, please @randomuser – MB_Coder Jun 13 '18 at 00:22
  • please how to read my data from `DailyInfo` class inside the Override method `getItem`? @randomuse – MB_Coder Jun 13 '18 at 00:47
  • Specified **exactly** where to include the changes. Check https://developer.android.com/reference/android/widget/Adapter.html#getView(int,%20android.view.View,%20android.view.ViewGroup) – randomuser Jun 13 '18 at 23:33
  • my problem is with the adapter because the Override method `getView` display empty `ListView` but I need to display my data in the firebase database – MB_Coder Jun 14 '18 at 05:10
  • You didn't make the changes to your getView class. Still inside the if block – randomuser Jun 14 '18 at 14:49
1

You are modifying the view only when it hasn't been created before, which won't be the case the next time around, that's it, when the data is available. So, based on your code (should consider including a holder btw):

public View getView(int position, View v, ViewGroup parent) {
    View mView = v;
    if (mView == null) {
        LayoutInflater vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        mView = vi.inflate(R.layout.custom_list, null, false);
    }
    TextView text = (TextView) mView.findViewById(R.id.textView);
    text.setText(getItem(position));
    if (items.isEmpty()) {
         // Set holder color
    } else {
         text.setTextColor(Color.WHITE);
    }   
    return mView;
}
randomuser
  • 603
  • 4
  • 16