I have a RideList class that is called from an Activity class that retrieves data from a Firebase database. However, when I debug my program the code within my addValueEventListener is never being reached.
public class RideList {
private ArrayList<Ride> listofRides;
public Firebase myFirebase = new Firebase("https://luminous-torch-1510.firebaseio.com/rides");
Context context;
public RideList(Context context) {
this.context = context;
this.listofRides = new ArrayList <Ride>();
}
public ArrayList<Ride> getRides() {
Firebase.setAndroidContext(context);
// Attach an listener to read the data at our rides reference
Query queryRef = myFirebase.orderByChild("timePosted");
try {
queryRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
System.out.println("There are " + snapshot.getChildrenCount() + " rides");
for (DataSnapshot postSnapshot : snapshot.getChildren()) {
String rideString = postSnapshot.getValue().toString();
String[] rideA = rideString.split(" ");
String value;
for (int i = 0; i < rideA.length - 1; i++) {
rideA[i] = rideA[i].substring(rideA[i].indexOf("=") + 1);
rideA[i] = rideA[i].substring(0, rideA[i].indexOf(","));
}
rideA[rideA.length - 1] = rideA[rideA.length - 1].substring(rideA[rideA.length - 1].indexOf("=") + 1);
rideA[rideA.length - 1] = rideA[rideA.length - 1].substring(0, rideA[rideA.length - 1].indexOf("}"));
double numOfPassengers = Double.valueOf(rideA[6]);
double fare = Double.valueOf(rideA[4]);
double distance = Double.valueOf(rideA[3]);
String origin = rideA[7];
String destination = rideA[2];
double maxPassengers = Double.valueOf(rideA[5]);
String departTime = rideA[1];
String arrivalTime = rideA[0];
String timePosted = rideA[8];
String title = rideA[9];
String type1 = rideA[10];
boolean type;
if (type1.equals("offer"))
type = false;
else
type = true;
Ride ride = new Ride(numOfPassengers, fare, distance, origin, destination, maxPassengers, departTime, arrivalTime,
timePosted, title, type);
listofRides.add(ride);
}
}
#Override
public void onCancelled(FirebaseError firebaseError) {
System.out.println("The read failed: " + firebaseError.getMessage());
}
});
Thread.sleep(2000);
} catch (InterruptedException e) {
return null;
}
return listofRides;
}
}
This code is being called from an OnCreate function of an Activity class. Any idea on why the listener code is never being entered/executed?
Edit: Here is the code on how this function is being called in the activity class.
list = (ListView) findViewById(R.id.showrides_listView);
Firebase.setAndroidContext(this);
RideList rl = new RideList(this);
ArrayList arrayList = rl.getRides();
// Adapter: You need three parameters 'the context, id of the layout (it will be where the data is shown),
// and the array that contains the data
ArrayAdapter adapter = new ArrayAdapter<Ride>(getApplicationContext(), android.R.layout.simple_spinner_item, arrayList){
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = super.getView(position, convertView, parent);
TextView text = (TextView) view.findViewById(android.R.id.text1);
text.setTextColor(Color.BLACK);
return view;
}
};
// Here, you set the data in your ListView
list.setAdapter(adapter);
adapter.notifyDataSetChanged();
FloatingActionButton myFab = (FloatingActionButton) findViewById(R.id.showrides_fab);
myFab.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
startCreateRideActivity();
}
});
Your data is being loaded asynchronously (and after that continuously synchronized) from Firebase. Putting a Thread.sleep() in there is not going to change that fact.
You can easily see what happens if you add a few log statements:
public ArrayList<Ride> getRides() {
Query queryRef = myFirebase.orderByChild("timePosted");
try {
System.out.println("Adding listener");
queryRef.addValueEventListener(new ValueEventListener() {
public void onDataChange(DataSnapshot snapshot) {
// THIS CODE IS CALLED ASYNCHRONOUSLY
System.out.println("Got data from Firebase");
}
public void onCancelled(FirebaseError firebaseError) {
}
});
System.out.println("Starting sleep");
Thread.sleep(2000);
} catch (InterruptedException e) {
return null;
}
System.out.println("Returning rides");
return listofRides;
}
The output is likely:
Adding listener
Starting sleep
Returning rides
Got data from Firebase
You're trying to make an asynchronous process synchronous, which is a recipe for headaches and a bad user experience. Instead of writing up a solution here, I'll link to an answer I wrote 15 minutes ago to the same problem: Retrieving ArrayList<Object> from FireBase inner class
Related
I have a MySQL database of two columns displayed in an android ListView. I use Retrofit 1.9 to get the data from MySQL. The adapter for the ListView is a BaseAdapter and I don't have a DatabaseHelperclass. When I add a data in the ListView from my mobile phone, it doesn't refresh the ListView. I have to close and restart the app. I try to refresh with listViewAdapter.notifyDataSetChanged();.
This is the fragment where the listview is:
public class rightFragment extends Fragment {
String BASE_URL = "http://awebsite.com";
View view;
ListView listView;
ListViewAdapter listViewAdapter;
Button buttondisplay;
Button buttonadd;
EditText new_id;
EditText newWordFra;
EditText newWordDeu;
ArrayList<String> id = new ArrayList<>();
ArrayList<String> fra = new ArrayList<>();
ArrayList<String> deu = new ArrayList<>();
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(com.example.geeko.Deu.R.layout.fragment_right, container, false);
listView = (ListView) view.findViewById(com.example.geeko.Deu.R.id.listView); //<<<< ADDED NOTE use your id
listViewAdapter = new ListViewAdapter(getActivity(), id, fra, deu);
displayData();
buttondisplay = (Button) view.findViewById(com.example.geeko.Deu.R.id.buttondisplay);
buttonadd = (Button) view.findViewById(com.example.geeko.Deu.R.id.buttonadd);
buttondelete = (Button) view.findViewById(com.example.geeko.Deu.R.id.newID);
newWordFra = (EditText) view.findViewById(com.example.geeko.Deu.R.id.newWordFra);
newWordDeu = (EditText) view.findViewById(com.example.geeko.Deu.R.id.newWordDeu);
buttonadd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//Toast.makeText(MainActivity.this , "button add", Toast.LENGTH_LONG).show();
insert_data();
listViewAdapter.notifyDataSetChanged();
}
});
buttondisplay.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (buttondisplay.getText().toString().contains("Show")) {
listView.setAdapter(listViewAdapter);
buttondisplay.setText("Hide");
} else {
listView.setAdapter(null);
buttondisplay.setText("Show");
}
}
});
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long ids) {
new_id.setText(id.get(position));
newWordFra.setText(fra.get(position));
newWordDeu.setText(deu.get(position));
}
});
return view;
}
public void insert_data() {
RestAdapter adapter = new RestAdapter.Builder()
.setEndpoint(BASE_URL) //Setting the Root URL
.build();
AppConfig.insert api = adapter.create(AppConfig.insert.class);
api.insertData(
newWordFra.getText().toString(),
newWordDeu.getText().toString(),
new Callback<Response>() {
#Override
public void success(Response result, Response response) {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(result.getBody().in()));
String resp;
resp = reader.readLine();
Log.d("success", "" + resp);
JSONObject jObj = new JSONObject(resp);
int success = jObj.getInt("success");
if(success == 1){
Toast.makeText(getActivity(), "Successfully inserted", Toast.LENGTH_SHORT).show();
} else{
Toast.makeText(getActivity(), "Insertion Failed", Toast.LENGTH_SHORT).show();
}
} catch (IOException e) {
Log.d("Exception", e.toString());
} catch (JSONException e) {
Log.d("JsonException", e.toString());
}
}
#Override
public void failure(RetrofitError error) {
Toast.makeText(getActivity(), error.toString(), Toast.LENGTH_LONG).show();
}
}
);
}
public void displayData() {
RestAdapter adapter = new RestAdapter.Builder()
.setEndpoint(BASE_URL) //Setting the Root URL
.build();
AppConfig.read api = adapter.create(AppConfig.read.class);
api.readData(new Callback<JsonElement>() {
#Override
public void success(JsonElement result, Response response) {
String myResponse = result.toString();
Log.d("response", "" + myResponse);
try {
JSONObject jObj = new JSONObject(myResponse);
int success = jObj.getInt("success");
if (success == 1) {
JSONArray jsonArray = jObj.getJSONArray("details");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jo = jsonArray.getJSONObject(i);
id.add(jo.getString("id"));
fra.add(jo.getString("fra"));
deu.add(jo.getString("deu"));
}
listView.setAdapter(listViewAdapter);
} else {
Toast.makeText(getActivity(), "No Details Found", Toast.LENGTH_SHORT).show();
}
} catch (JSONException e) {
Log.d("exception", e.toString());
}
}
#Override
public void failure(RetrofitError error) {
Log.d("Failure", error.toString());
Toast.makeText(getActivity(), error.toString(), Toast.LENGTH_LONG).show();
}
}
);
}
}
This is the listViewAdpater class :
public class ListViewAdapter extends BaseAdapter {
private final Context context;
private ArrayList<String> id = new ArrayList<String>();
private ArrayList<String> fra = new ArrayList<String>();
private ArrayList<String> deu = new ArrayList<String>();
LayoutInflater layoutInflater;
public ListViewAdapter(Context ctx, ArrayList<String> id, ArrayList<String> fra, ArrayList<String> deu) {
this.context = ctx;
this.id = id;
this.fra = fra;
this.deu = deu;
}
#Override
public int getCount() {
return id.size();
}
#Override
public Object getItem(int position) {
return id.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#SuppressLint("ViewHolder")
#Override
public View getView(final int position, View view, ViewGroup parent) {
final Holder holder;
if (view == null) {
layoutInflater = (LayoutInflater) context.getSystemService
(Context.LAYOUT_INFLATER_SERVICE);
view = layoutInflater.inflate(R.layout.list_item, null);
holder = new Holder();
holder.txt_fra = (TextView) view.findViewById(R.id.fra);
holder.txt_deu = (TextView) view.findViewById(R.id.deu);
view.setTag(holder);
} else {
holder = (Holder) view.getTag();
}
holder.txt_fra.setText(fra.get(position));
holder.txt_deu.setText(deu.get(position));
return view;
}
static class Holder {
TextView txt_fra, txt_deu;
}
}
Should I create a method to refresh my ListView?
First of all I would suggest to remove the unnecessary initialization of your variables inside the Adapter:
private ArrayList<String> id = new ArrayList<String>();
private ArrayList<String> fra = new ArrayList<String>();
private ArrayList<String> deu = new ArrayList<String>();
By assigning the pointer from your fragment you will already assign an initialized ArrayList. You want both pointers to point at the same ArrayList Object so changes apply to both.
Apparently, the data stored in the Adapter is not being updated correctly. I would suggest to debug your app - setting the breakpoint so that you can see the data that the Adapter stores after an update.
The idea of writing a method for updates has already been implemented with the notifyDataSetChanged(). Just override the method in your adapter and do eventual changes before calling the super.notifyDataSetChanged().
If you have any success with those changes let us know.
buttonadd.setOnClickListener(new View.OnClickListener() {
...
insert_data();
listViewAdapter.notifyDataSetChanged();
}
});
In your onClickListener, you are calling insert_data(), followed by listViewAdapter.notifyDataSetChanged()
insert_data() method is sending a network request to retrieve the data to populate the list. BUT, you are calling notifyDataSetChanged BEFORE the network request is done. That's why the listView is empty, and will stay empty. You need to wait AFTER the network request and AFTER you have populated your ArrayList with the data to call notifyDataSetChanged.
How do we know the network request is done? Simply at the end of the callback (which you've implemented):
new Callback<Response>() {
#Override
public void success(Response result, Response response) {...
At the end of the success method, you call listViewAdapter.notifyDataSetChanged() method.
Hope that makes sense! Try it and let us know what happens
I've founded a solution. I've added getActivity.recreate(); in the method insert_data.
public void success(Response result, Response response) {
try {
BufferedReader reader = new BufferedReader
(new InputStreamReader(result.getBody().in()));
String resp;
resp = reader.readLine();
Log.d("success", "" + resp);
JSONObject jObj = new JSONObject(resp);
int success = jObj.getInt("success");
if(success == 1){
Toast.makeText(getActivity(), "Successfully inserted",
Toast.LENGTH_SHORT).show();
getActivity().recreate();
} else{
Toast.makeText(getActivity(), "Insertion Failed",
Toast.LENGTH_SHORT).show();
}
} catch (IOException e) {
Log.d("Exception", e.toString());
} catch (JSONException e) {
Log.d("JsonException", e.toString());
}
}
I'm not sure that is the best solution but it works.
I'm working on a chat app using nkzawa socket-io library. I have successfully sent messages to server and retrieved them in my log cat. I am unable to update the ui as the get message event was not done in the adapter.
I want to be able to separate the messages based on uid as mine or others and update ui properly. So far, I've been confused how to go about the adapter, should I retrieve the messages in adapter or in main UI?
Here's my adapter code:
public class MessagesAdapter extends RecyclerView.Adapter<MessagesViewHolder> {
private static final String TAG = MessagesAdapter.class.getSimpleName();
private Context context;
private DBHelper helper;
private TingTingUser user;
private List<HomeMessage> messageList;
public MessagesAdapter(Context context, List<HomeMessage> messageList) {
this.context = context;
this.messageList = messageList;
helper = new DBHelper(context);
}
#Override
public MessagesViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View msgView = LayoutInflater.from(parent.getContext()).inflate(R.layout.messages_layout, parent, false);
return new MessagesViewHolder(msgView);
}
#Override
public void onBindViewHolder(MessagesViewHolder holder, int position) {
HomeMessage message = messageList.get(position);
//holder.upDateUI();
}
#Override
public int getItemCount() {
if (messageList.size() == 0) {
return 0;
}
return messageList.size();
}
public void upDateUI(String usersId) {
user = helper.getCurrentUser(1);
String currUid = user.getUserId();
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.messages_layout, null, false);
MessagesViewHolder holder = new MessagesViewHolder(view);
Log.d(TAG, "Uid form DB is:\t" + currUid);
if (usersId != currUid) {
holder.mainLayout.setGravity(Gravity.LEFT);
holder.nameLayout.setVisibility(View.VISIBLE);
holder.msgHolderLayout.setBackgroundResource(R.drawable.receiver_msg_bkg);
} else {
holder.mainLayout.setGravity(Gravity.RIGHT);
holder.nameLayout.setVisibility(View.GONE);
holder.msgHolderLayout.setBackgroundResource(R.drawable.sender_msg_bkg);
}
} }
Here's my method to retrieve all socket messages:
private void getPublicMessages(){
String get_event = "cc-" + chatRoomId;
Log.d(TAG, "Get Event Name is:\t " + get_event.toString());
mSocket.on(get_event, new Emitter.Listener() {
#Override
public void call(final Object... args) {
runOnUiThread(new Runnable() {
#Override
public void run() {
try {
JSONObject jsonObject = (JSONObject) args[0];
//JSONObject dataObject = jsonObject.getJSONObject();
String type = jsonObject.getString("type");
Log.d(TAG, "Message is of type:\t" + type);
JSONObject contentObject = jsonObject.getJSONObject("content");
String userId = contentObject.getString("userId");
String roomId = contentObject.getString("roomId");
String message = contentObject.getString("message");
String name = contentObject.getString("name");
String avatar = contentObject.getString("avatar");
Log.d(TAG, "Get Message is:\t" + message);
Log.d(TAG, "roomId:\t" + roomId);
Log.d(TAG, "Get userId is:\t" + userId);
Log.d(TAG, "Get name is:\t" + name);
Log.d(TAG, "Get avatar is:\t" + avatar);
TingTingUser otherUsers = new TingTingUser(userId, "Abhiram Labhani", "Unknown");
HomeMessage othersHomeMessages = new HomeMessage(message, otherUsers, System.currentTimeMillis());
List<HomeMessage> othersList = new ArrayList<>();
othersList.add(othersHomeMessages);
Log.d(TAG, "Other Messages size is:\t " + othersList.size());
messageList.add(othersHomeMessages);
messagesAdapter.notifyDataSetChanged();
Log.d(TAG, "All Messages list size is:\t " + messageList.size());
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
});
}
The values like name, message, etc are coming directly in activity. How should I update the ui, will this adapter code work or I should put this method in adapter and update accordingly?
Thanks all.
First thing you have to add the message received to the data source list you use in the Adapter.
Second thing you have to call
recyclerView.getAdapter().notifyItemInserted(position)
OR
recycerView.getAdapter().notifyItemRangeInserted(positionStart, itemCount);
second one is used to notify that multiple items are added.
I am creating an application with a list that list cards based on the value from the server.
I created a StudentCardArrayAdapter to achieve this and everything works fine. All the data has been populated in card list. also I able to get the values on button click in each card separately.
What I need is on clicking the button it will call a method requestion server for data asynchronously and get a value from the server and according to that value, i need to change the button text in that particular card.
My StudentCardArrayAdapter code:
public class StudentCardArrayAdapter extends ArrayAdapter<StudentCard> {
private static final String TAG = "CardArrayAdapter";
private List<StudentCard> cardList = new ArrayList<StudentCard>();
private Context mContext;
String selected = "0";
PreferenceHelper prefs;
CardViewHolder viewHolder;
View row;
ProgressDialog pd;
static class CardViewHolder {
TextView studentname;
TextView stop;
Button selectbutton;
CircleImageView imageId;
}
public StudentCardArrayAdapter(Context context, int textViewResourceId) {
super(context, textViewResourceId);
this.mContext = context;
prefs = new PreferenceHelper(this.mContext);
pd = new ProgressDialog(this.mContext);
}
#Override
public void add(StudentCard object) {
cardList.add(object);
super.add(object);
}
#Override
public int getCount() {
return this.cardList.size();
}
#Override
public StudentCard getItem(int index) {
return this.cardList.get(index);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
row = convertView;
if (row == null) {
LayoutInflater inflater = (LayoutInflater) this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.student_card, parent, false);
viewHolder = new CardViewHolder();
viewHolder.studentname = (TextView) row.findViewById(R.id.studentname);
viewHolder.stop = (TextView) row.findViewById(R.id.stop);
viewHolder.selectbutton = (Button) row.findViewById(R.id.selectbutton);
viewHolder.imageId = (CircleImageView) row.findViewById(R.id.imageId);
row.setTag(viewHolder);
} else {
viewHolder = (CardViewHolder)row.getTag();
}
StudentCard card = getItem(position);
viewHolder.studentname.setText(card.getStudName());
viewHolder.studentname.setTextColor(Color.parseColor("#000000"));
viewHolder.stop.setText(card.getStudStop());
viewHolder.stop.setTextColor(Color.parseColor("#000000"));
if(card.getSelected().equals("1")){
viewHolder.selectbutton.setText(mContext.getResources().getString(R.string.selected));
viewHolder.selectbutton.setEnabled(false);
}
else{
viewHolder.selectbutton.setText(mContext.getResources().getString(R.string.select));
viewHolder.selectbutton.setEnabled(true);
}
final String studid = card.getStudId();
final String busname = prefs.getString("busname", "0");
final String schoolid = prefs.getString("schoolid", "");
viewHolder.selectbutton.setOnClickListener(new View.OnClickListener()
{
String updatedvalue = "0";
#Override
public void onClick(View v)
{
Log.e("studid",studid);
Log.e("busname",busname);
Log.e("schoolid",schoolid);
selectstudent(v, studid, busname, schoolid,mContext);
//Toast.makeText(v.getContext(), amountinfo, Toast.LENGTH_SHORT).show();
/*SnackbarManager.show(Snackbar.with(this) // context
.text(amountinfo));*/
}
});
Picasso.with(mContext).load(card.getImageUrl()).fit().error(R.mipmap.ic_launcher).into(viewHolder.imageId);
return row;
}
public void selectstudent(final View v, String studid, String busname, String schoolid, final Context mContext) {
String returnedselected = "0";
Log.e("BASE_URL_STUDENT_UPDATE", Constants.BASE_URL_STUDENT_UPDATE + "?studid=" + studid+"&busname="+busname+"&schoolid="+schoolid);
RestClientHelper.getInstance().get(Constants.BASE_URL_STUDENT_UPDATE + "?studid=" + studid+"&busname="+busname+"&schoolid="+schoolid, new RestClientHelper.RestClientListener() {
#Override
public void onSuccess(String response) {
Log.e("RESULT", response);
try {
JSONObject result = new JSONObject(response);
JSONArray posts = result.optJSONArray("status");
for (int i = 0; i < posts.length(); i++) {
JSONObject post = posts.optJSONObject(i);
String status = post.optString("status");
if (status.equals("true")) {
selected = post.optString("selected");
} else {
selected = post.optString("selected");
String error = post.optString("error");
SnackbarManager.show(Snackbar.with(getContext()) // context
.text(error));
}
}
} catch (JSONException e) {
e.printStackTrace();
} catch (Exception e) {
} finally {
if(selected.equals("1")){
viewHolder.selectbutton.setText(mContext.getResources().getString(R.string.selected));
viewHolder.selectbutton.setEnabled(false);
}
}
}
#Override
public void onError(String error) {
Log.e("error", error);
selected = "0";
}
});
}
}
I used the below code but nothing works.. No error also.. and not change in button text.I get value of selected as 1 from server.
if(selected.equals("1")){
viewHolder.selectbutton.setText(mContext.getResources().getString(R.string.selected));
viewHolder.selectbutton.setEnabled(false);
}
I am new to android.. and is stuck here. Please help me out.
FINALLY IT WORKED
As changes mention by Krish, I updated the code suggested by him.
And added this changes in onClick it worked
if(card.getSelected().equals("1")){
viewHolder.selectbutton.setText(mContext.getResources().getString(R.string.selected));
viewHolder.selectbutton.setEnabled(false);
}
Change the code like this,
public void selectstudent(StudentCard card, String studid, String busname, String schoolid, final Context mContext) {
String returnedselected = "0";
Log.e("BASE_URL_STUDENT_UPDATE", Constants.BASE_URL_STUDENT_UPDATE + "?studid=" + studid+"&busname="+busname+"&schoolid="+schoolid);
RestClientHelper.getInstance().get(Constants.BASE_URL_STUDENT_UPDATE + "?studid=" + studid+"&busname="+busname+"&schoolid="+schoolid, new RestClientHelper.RestClientListener() {
#Override
public void onSuccess(String response) {
Log.e("RESULT", response);
try {
JSONObject result = new JSONObject(response);
JSONArray posts = result.optJSONArray("status");
for (int i = 0; i < posts.length(); i++) {
JSONObject post = posts.optJSONObject(i);
String status = post.optString("status");
if (status.equals("true")) {
selected = post.optString("selected");
} else {
selected = post.optString("selected");
String error = post.optString("error");
SnackbarManager.show(Snackbar.with(getContext()) // context
.text(error));
}
}
} catch (JSONException e) {
e.printStackTrace();
} catch (Exception e) {
} finally {
if(selected.equals("1")){
card.setSelected("1");
notifyDataSetChanged();
}
}
}
#Override
public void onError(String error) {
Log.e("error", error);
selected = "0";
}
});
}
and change this line like this ,
final StudentCard card = getItem(position);
and call method inside onclick.
selectstudent(card, studid, busname, schoolid,mContext);
I'm new to Android and Firebase environment but I'm working on it !
I'm working on an Android app and I need to read some values related to a child within a Firebase database. After this initial read, I need to modify / update these values and write them to the same child.
public class MainActivity extends Activity {
public static class Shoe extends JSONObject {
private String name;
private int size;
Shoe(){
// Default constructor required for calls to
// DataSnapshot.getValue(Shoe.class)
}
Shoe( String nm, int sz) { this.name = nm; this.size = sz; }
public int getSize() { return this.size; }
public void setSize(int sz) { this.size = sz; }
public String getName() { return this.name;}
public void setName(String nm) {this.name = nm; }
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate");
// Write a message to the database
FirebaseDatabase database = FirebaseDatabase.getInstance();
database.setPersistenceEnabled(true);
DatabaseReference myRefTarget = database.getReference("target");
Shoe obj1 = new Shoe("item ID 1", 99);
Shoe obj2 = new Shoe("item ID 2", 1000);
final Shoe obj_old = new Shoe();
Shoe obj_new = new Shoe();
DatabaseReference myRefDeviceA = myRefTarget.child("deviceA").getRef();
myRefDeviceA.keepSynced(true);
myRefDeviceA.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot)
{
obj_old.setName( dataSnapshot.getValue(Shoe.class).getName());
obj_old.setSize( dataSnapshot.getValue(Shoe.class).getSize());
Log.d(TAG_CLOUD, "from onDataChange: deviceA = " + obj_old.getName() + ", " + obj_old.getSize());
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
// HERE
Log.d(TAG_CLOUD, "Name = " + obj_old.getName() + ", Size = " + obj_old.getSize());
}
the issue I got is that the read operation is asynchronously done..
D/FROM CLOUD: Name = null, Size = 0
D/FROM CLOUD: from onDataChange: deviceA = item ID 1, 99
how can adapt / modify the source code in such way that first "read" to give me values different than null and '0' ? "HERE" line
eg.
Name = item ID 1 Size = 99
Thank you.
You don't suppose to perform networking operations on the UI thread.
If you want to display the data in the activity, you should show a loading dialog in the onCreate method, and then after fetching the data close the dialog and update the activity view
I need to add my Items one by one to my RcyclerView for example add first item to recyclerView and show then add another item....
I have a volley that connect to a service then get me some data, in this volley I call a method :
private void makeJsonArryReq(String uri) {
userPointList = new ArrayList<>();
orginal = new ArrayList<>();
final JsonArrayRequest req = new JsonArrayRequest(uri,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
orginal = MarketingPoints_JSONParser.FeedOriginal(response.toString(), mUser_Code, ReportActivity.this);
userPointList = MarketingPoints_JSONParser.parseFeed(response.toString(), mUser_Code, ReportActivity.this);
FillList();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d("Custom Log Error", "Error: " + error.getMessage());
}
});
AppController.getInstance().addToRequestQueue(req, tag_json_arry);
}
when I call this method FillList(); it fill and show first item on RecyclerView,How can I listen to adapter for finalized and call FillList(); again for next item .
My FillList():
public void FillList() {
Geocoder geocoder = new Geocoder(activity, Locale.getDefault());
List<Address> addresses;
StepModel stp = null;
List<StepModel> Step = new ArrayList<>();
if (check < userPointList.size()) {
try {
addresses = geocoder.getFromLocation(userPointList.get(check).getLat(), userPointList.get(check).getLng(), 1);
stp = new StepModel();
stp.setsCity(addresses.get(0).getAdminArea());
stp.setsStreet(addresses.get(0).getThoroughfare());
stp.setSlat(userPointList.get(check).getLat());
stp.setSlng(userPointList.get(check).getLng());
stp.setSdate(userPointList.get(check).getDate());
stp.setStime(userPointList.get(check).getTime());
stp.setsCounts(userPointList.get(check).getCounts());
stp.setSprofilePhoto(userPointList.get(check).getProfilePhoto());
stp.setsUserCode(userPointList.get(check).getUserCode());
Step.add(stp);
} catch (IOException e) {
e.printStackTrace();
}
pointAdapter = new PointsList_Adapter(Step, ReportActivity.this,this, city, street);
Points_Recycler.setAdapter(pointAdapter);
pointAdapter.notifyDataSetChanged();
check++;
}else {
return;
}
}
Explain :
I connect to a service then I get a json then I convert it and store in a List.In my json I have two specific data (Lat and lng) that I should get name country and name street(For example 100 lat lng) then show on recyclerView but it get long time because I should fill recyclerView on by one.
My adapter :
public class PointsList_Adapter extends RecyclerView.Adapter<PointsList_Adapter.ViewHolder> {
int count = 0;
private List<StepModel> mpList;
public static Activity activity;
public static boolean flagItem = true;
public static boolean flagToast = true;
private mstep Mstep;
public PointsList_Adapter(List<StepModel> userCodeList, Activity activity) {
this.mpList = userCodeList;
this.activity = activity;
}
#Override
public PointsList_Adapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// create a new view
View itemLayoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.listpoints_cardview, null);
// create ViewHolder
ViewHolder viewHolder = new ViewHolder(itemLayoutView);
return viewHolder;
}
#Override
public void onBindViewHolder(PointsList_Adapter.ViewHolder viewHolder, final int position) {
String dateValue = mpList.get(position).getDate();
final String countValue = String.valueOf(mpList.get(position).getCounts());
final Double lat = mpList.get(position).getLat();
final Double lng = mpList.get(position).getLng();
final String userCode = mpList.get(position).getUserCode();
final String time = mpList.get(position).getTime();
final int counts = mpList.get(position).getCounts();
final String city = mpList.get(position).getCity();
final String street = mpList.get(position).getStreet();
viewHolder.txtDate.setText(dateValue);
viewHolder.txtPoints.setText(lat + " , " + lng);
viewHolder.txtTime.setText(time);
viewHolder.txtAddress.setText(city + " , " + street);
viewHolder.txtCount.setText(countValue);
}
#Override
public int getItemCount() {
return mpList.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView txtDate, txtPoints, txtTime, txtAddress, txtCount;
public LinearLayout lLstPoints;
public ViewHolder(View itemLayoutView) {
super(itemLayoutView);
txtDate = (TextView) itemLayoutView.findViewById(R.id.txtDate);
txtPoints = (TextView) itemLayoutView.findViewById(R.id.txtPoints);
txtTime = (TextView) itemLayoutView.findViewById(R.id.txtTime);
txtAddress = (TextView) itemLayoutView.findViewById(R.id.txtAddress);
txtCount = (TextView) itemLayoutView.findViewById(R.id.txtCount);
lLstPoints = (LinearLayout) itemLayoutView.findViewById(R.id.lLstPoints);
}
}
}
Please add below method in your adapter:
public reloadList(ArrayList<String> mpList) {
this.mpList.addAll(mpList);
}
When you want to update list or want to add one more item in your listview, use below code:
public void FillList() {
Geocoder geocoder = new Geocoder(activity, Locale.getDefault());
List<Address> addresses;
StepModel stp = null;
List<StepModel> Step = new ArrayList<>();
if (check < userPointList.size()) {
try {
addresses = geocoder.getFromLocation(userPointList.get(check).getLat(), userPointList.get(check).getLng(), 1);
stp = new StepModel();
stp.setsCity(addresses.get(0).getAdminArea());
stp.setsStreet(addresses.get(0).getThoroughfare());
stp.setSlat(userPointList.get(check).getLat());
stp.setSlng(userPointList.get(check).getLng());
stp.setSdate(userPointList.get(check).getDate());
stp.setStime(userPointList.get(check).getTime());
stp.setsCounts(userPointList.get(check).getCounts());
stp.setSprofilePhoto(userPointList.get(check).getProfilePhoto());
stp.setsUserCode(userPointList.get(check).getUserCode());
Step.add(stp);
} catch (IOException e) {
e.printStackTrace();
}
// Just update your list and call notifyDataSetChanged()
pointAdapter .reloadList(Step);
pointAdapter .notifyDataSetChanged();
check++;
}else {
return;
}
}
Initialize your adapter as below:
ArrayList<StepModel> userCodeList = new ArrayList<StepModel>();
pointAdapter = new PointsList_Adapter(userCodeList , activity) ;
Thank You.
After retrieving all data from server at once, inside Filllist() method you should use for, while or do..while loops to iterate your code.You have used if conditional loop that will run only once.
Else, you can create a method inside adapter to add item to your list and then call notifydatasetchanged() method there.
public void add(Object obj){
mArraylist.add(obj);
notifyDataSetChanged();
}