I'm simply just trying to populate data from Firebase Database into my listview. The logs are showing the data is being retrieved, but the adapter won't set the values to the text in a single list item in the list? All it says is "No setter/field for INSERT VALUE". Which makes me think that I didn't have my setters made correctly but there were auto generated by Android Studio. I don't know what I am missing here. Any help is appreciated.
NODE OBJECT
package com.megliosolutions.ipd.Objects;
import android.graphics.Bitmap;
/**
* Created by Meglio on 6/13/16.
*/
public class NodeObject {
public String mStaticAddress;
public String mLat;
public String mLong;
public NodeObject(){
//needed for firebase
}
public NodeObject(String address, String lat, String Long){
this.mStaticAddress = address;
this.mLat = lat;
this.mLong = Long;
}
public String getmStaticAddress() {
return mStaticAddress;
}
public void setmStaticAddress(String mStaticAddress) {
this.mStaticAddress = mStaticAddress;
}
public String getmLat() {
return mLat;
}
public void setmLat(String mLat) {
this.mLat = mLat;
}
public String getmLong() {
return mLong;
}
public void setmLong(String mLong) {
this.mLong = mLong;
}
}
STATIC LISTADAPTER
/**
* Created by Meglio on 6/14/16.
*/
public class StaticListAdapter extends ArrayAdapter<NodeObject> {
public static String TAG = StaticListAdapter.class.getSimpleName();
public Context mContext;
public List<NodeObject> mNodes;
public class ViewHolder {
TextView mStaticAddress;
TextView mLAT;
TextView mLONG;
}
@Override
public int getCount() {
return mNodes.size();
}
public StaticListAdapter(Context context, List<NodeObject> objects) {
super(context, R.layout.activity_main, objects);
this.mContext = context;
this.mNodes = objects;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = new ViewHolder();
NodeObject node = mNodes.get(position);
if (convertView == null) {
convertView = LayoutInflater.from(this.mContext).inflate(R.layout.node_item, null);
holder.mLONG = (TextView) convertView.findViewById(R.id.node_item_LONG);
holder.mStaticAddress = (TextView) convertView.findViewById(R.id.node_item_IP);
holder.mLAT = (TextView) convertView.findViewById(R.id.node_item_LAT);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.mStaticAddress.setText(node.getStaticAddress());
holder.mLONG.setText(node.getLongitude());
holder.mLAT.setText(node.getLatitude());
return convertView;
}
}
MAINACTIVITY
public class MainActivity extends AppCompatActivity {
public static String TAG = MainActivity.class.getSimpleName();
public ListView main_ListView;
public FirebaseAuth mAuth;
public FirebaseUser mUser;
public DatabaseReference mDatabase;
//Strings
public String static_ip;
public String lat = "5.0";
public String mLong = "4.0";
public String currentUser;
//Adapters
public StaticListAdapter listAdapter;
//Node Object
NodeObject node;
public List<NodeObject> nodesList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Instances
mAuth = FirebaseAuth.getInstance();
mUser = mAuth.getCurrentUser();
mDatabase = FirebaseDatabase.getInstance().getReference();
currentUser = mUser.getUid();
main_ListView = (ListView)findViewById(R.id.Main_listview);
//Toolbar
if (getSupportActionBar() != null) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
//[End of Toolbar]
nodesList = new ArrayList<>();
retrieveData();
listAdapter = new StaticListAdapter(getApplicationContext(),nodesList);
main_ListView.setAdapter(listAdapter);
Log.i(TAG, "USER: " + currentUser);
}
private void retrieveData() {
mDatabase.child("nodes").child(mUser.getUid())
.addChildEventListener(new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Log.d(TAG, "onChildAdded:" + dataSnapshot.getKey());
NodeObject nodeObject = dataSnapshot.getValue(NodeObject.class);
listAdapter.add(nodeObject);
listAdapter.setNotifyOnChange(true);
}
@Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
@Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
@Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case R.id.getGPS:
//nothing
return true;
case R.id.addNode:
addNode();
return true;
case R.id.logout:
signOut();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private void signOut() {
mAuth.signOut();
Intent intent = new Intent(MainActivity.this, Login.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
Toast.makeText(getApplicationContext(), "Logging Out.", Toast.LENGTH_SHORT).show();
startActivity(intent);
}
private void addNode() {
//AlertDialog
final AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
dialogBuilder.setTitle("Dude, assign something...");
LayoutInflater inflater = this.getLayoutInflater();
View dialogView = inflater.inflate(R.layout.main_add_node_dialog, null);
dialogBuilder.setView(dialogView);
final EditText editText = (EditText)
dialogView.findViewById(R.id.static_et);
dialogBuilder.setPositiveButton("Assign", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
static_ip = editText.getText().toString();
String ip = static_ip;
node = new NodeObject(ip, lat, mLong);
mDatabase.child("nodes").child(currentUser).push().setValue(node);
Toast.makeText(getApplicationContext(), "Static IP: " + static_ip + " assigned!"
, Toast.LENGTH_SHORT).show();
}
}).
setNegativeButton("Or Not...", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(getApplicationContext(), "Fine, nvm then..."
, Toast.LENGTH_SHORT).show();
}
});
dialogBuilder.create().show();
}
}
Debugging shows that I am able to get everything client side. Logs show this as well.
06-18 18:25:42.981 12962-12962/com.megliosolutions.ipd D/MainActivity: zHF4TGnRvkeXEbKiLegiUNLGHX12:{-KKLeBAe9pV1Umm3qQMo={mStaticAddress=26161910494949, mLong=3.0, mLat=2.0}, -KKG_ACFvdX7aJOR98-o={mStaticAddress=10.223.22.250, mLong=3.0, mLat=2.0}, -KKWKMZS7WkE_xWbL3rC={mStaticAddress=, mLong=4, mLat=5}, -KKQQLITf9-7iMFlqEWR={mStaticAddress=123123123123, mLong=3.0, mLat=2.0}, -KKG_J6PKwogjBFdk52Z={mStaticAddress=10.333.555.888, mLong=3.0, mLat=2.0}}
UPDATE
The part that didn't make sense to me, but I'm sure makes sense to those who know it very well. Is comprehending what I'm reading the firebase documentation. I read over it a few time, but I guess it just wasn't clicking. I figured out that structuring the data in firebase is KEY. Without that you can't code properly because everything relies on that. Firebase makes it easy to use now that I see it working. I will be making a blog post on this to explain my troubles and how to surpass them so no one else runs into this mess. The below code will build a functional listview with firebase backend!
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Log.d(TAG, "onChildAdded:" + dataSnapshot.getKey());
NodeObject nodeObject = dataSnapshot.getValue(NodeObject.class);
listAdapter.add(nodeObject);
listAdapter.setNotifyOnChange(true);
}
In retrieveData()
, you should be using a ChildEventListener, not a ValueEventListener
. You are adding Node
objects as children of node/$uid
with the keys generated by push()
. The ValueEventListener
is returning a Map<String,Object>
containing all of the Nodes
. That is shown in the logcat
output you posted. You can use the onChildAdded()
callback of ChildEventListener
to get each Node
as it is created and then add it to your adapter.
The warning is because the casing mismatches between your field and you setter.
Following the examples in the Firebase documentation, this seems like the better way to model the Java class:
public class NodeObject {
public String staticAddress;
public String lat;
public String lon;
public NodeObject(){
//needed for firebase
}
public NodeObject(String address, String lat, String lon){
this.staticAddress = address;
this.lat = lat;
this.lon = lon;
}
}
As an added bonus this will lead to more sensible JSON property names too.
I had the same issue just now & the answer was pretty frustrating.
I think that the issue is with your naming convention. For example, it looks like you named a variable mLat
, and then your accessors/mutators are getmLat()
and setmLat()
. I think when Firebase is doing the deserialization, they rely on certain naming. For example, if you have a member variable named lat
, you will need to have getLat()
and setLat()
.
For your case, you might just be able to change your methods to be getMLat()
and setMLat()
. Although I'd suggest changing up your conventions a bit in general.
As a side note, know that your naming is typically against convention. Generally, variables prefixed by m
are private member variables, accessed & mutated by public methods (like yours).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With