Update Data in Real Time when getting from server into RecylerView - java

I am getting json from Websockets and showing in recyler view. How do i update the list in real time when getting data from websockets?
My WebSocket Class
public final class EchoWebSocketListener extends WebSocketListener {
private static final int NORMAL_CLOSURE_STATUS = 1000;
private static final String TAG = "DashBoardScreen.this";
#Override
public void onOpen(WebSocket webSocket, Response response) {
super.onOpen(webSocket, response);
initially when connection is established i send some text to server
webSocket.send(builder.toString());
}
#Override
public void onMessage(WebSocket webSocket, String text) {
super.onMessage(webSocket, text);
in return server sends me data
output(text);
}
#Override
public void onMessage(WebSocket webSocket, ByteString bytes) {
super.onMessage(webSocket, bytes);
}
#Override
public void onClosing(WebSocket webSocket, int code, String reason) {
super.onClosing(webSocket, code, reason);
Log.d(TAG, "onClosing: ");
}
#Override
public void onClosed(WebSocket webSocket, int code, String reason) {
super.onClosed(webSocket, code, reason);
Log.d(TAG, "onClosed: ");
}
#Override
public void onFailure(WebSocket webSocket, Throwable t,Response response) {
super.onFailure(webSocket, t, response);
Log.d(TAG, "onFailure: ");
}
}
Output Method
private void output(final String text) {
runOnUiThread(new Runnable() {
#Override
public void run() {
*parsing json inside recyler view*
try {
JSONObject object = new JSONObject(text);
StringBuilder builder = new StringBuilder();
if (object.getBoolean("status")) {
JSONArray jsonArray = object.getJSONArray("events");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject values = jsonArray.getJSONObject(i);
final EventsDataModel dataModel = new EventsDataModel(
values.getString("service_Room_Number"),
values.getString("service_Name"),
values.getString("service_AssignedTo"),
values.getString("service_ID")
);
eventsDataModels.add(dataModel);
adapter = new EventListAdapter(eventsDataModels, context);
eventRecyclerView.setAdapter(adapter);
adapter.notifyDataSetChanged();
how exactly notifyDataSetChanged() works?
}
} else Toast.makeText(context, "No Events", Toast.LENGTH_SHORT).show();
System.out.println(builder.append(object.getString("status")));
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}

Whenever your dataModel has the new data
eventsDataModels.add(dataModel);
adapter = new EventListAdapter(eventsDataModels, context);
eventRecyclerView.setAdapter(adapter);
If you perform the above operations and performing adapter.notifyDataSetChanged();
Will notify the adapter the new data has arrived and have to update the RecyclerView with new dataModel.

Related

Android Extract String from Okhttp onResponse Function

I would like to get String value from onResponse function in OkHttp3 using Android Studio, which is
final String title_name = jsonarray_news_extract_Data(jsonStr, index)
in below codes.
I've tried insert String variable "a" in argument, but it said
Variable is accessed within inner class. Needs to be declared final
so that I declared as final then it said
Cannot Assign a Value to Final Variable
I tried to put
a = title_name;
after removed Handler method but still not work.
If you have any idea please help me out.
Thank you
public void news_From_API_Title(String url_news, final int index, final TextView textView, String a){
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(url_news)
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(#NotNull Call call, #NotNull IOException e) {}
#Override
public void onResponse(#NotNull Call call, #NotNull Response response) throws IOException {
final String jsonStr = Objects.requireNonNull(response.body()).string();
final String title_name = jsonarray_news_extract_Data(jsonStr, index);
Handler mainHandler = new Handler(Looper.getMainLooper());
mainHandler.post(new Runnable() {
#Override
public void run() {
a = title_name;
}
});
}
});
}
private String jsonarray_news_extract_Data(String jsonString_News, int index){
try {
JSONObject jsonObject = new JSONObject(jsonString_News);
JSONArray jsonArray = jsonObject.getJSONArray("Data");
return jsonArray.getJSONObject(index).getString("title");
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
You can use a custom interface like this:
interface ApiCallback{
void onOkHttpResponse(String data);
void onOkHttpFailure(Exception exception);
}
Then you pass not a String but an instance of ApiCallback into the method which is actually doing the call:
public void news_From_API_Title(String url_news, final int index, final TextView textView, ApiCallback callback){
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(url_news)
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(#NotNull Call call, #NotNull IOException e) {
callback.onOkHttpFailure(e);
}
#Override
public void onResponse(#NotNull Call call, #NotNull Response response) throws IOException {
final String jsonStr = Objects.requireNonNull(response.body()).string();
final String title_name = jsonarray_news_extract_Data(jsonStr, index);
Handler mainHandler = new Handler(Looper.getMainLooper());
mainHandler.post(new Runnable() {
#Override
public void run() {
callback.onOkHttpResponse(title_name);
}
});
}
});
}
Now you can use an implementation of ApiCallback as follows:
String url_news = "https://some.web.address/news";
int index = 7;
TextView textView;
news_From_API_Title(url_news, index, textView, new apiCallback(){
#Override
public void onOkHttpResponse(String data){
// do something with data here
Log.d("TEST", "data = " + data);
}
#Override
onOkHttpFailure(Exception exception){
// exception handling
}
});
Please note that it may be better from an architecture point of view if you don't pass the TextView as parameter into the method but instead set the text in onOkHttpResponse():
// TextView will be initialized before calling news_From_API_Title()
// either make TextView a field (then use "private")
// or declare it locally (then use "final")
private TextView textView;
// ... other code ...
String url_news = "https://some.web.address/news";
int index = 7;
// method will only take parameters which are not related to the UI
// since it's desirable to avoid tight coupling of networking and UI components
news_From_API_Title(url_news, index, new apiCallback(){
#Override
public void onOkHttpResponse(String data){
// do something with data here
// e.g. show data in TextView
textView.setText(data);
}
#Override
onOkHttpFailure(Exception exception){
// exception handling
}
});

How do I get return value onResponse

I know this is the answer, but I couldn't add it to my code.
How can I return value from function onResponse of Volley?
<------
like here I created interface.
I did it all.
I just don't know how to convert this my code to it, and how to use the return value in other activities.
public void priceDate(Context contex, final String coin) {
String URL = "https://min-api.cryptocompare.com/data/top/exchanges/full?fsym=BTC&tsym=USD&api_key=" + apiKey;
//String a =
//json_Parser = new JSONParser(_usd);
RequestQueue requestQueue = Volley.newRequestQueue(contex);
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, URL, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
//Log.d("Main",response.toString());}
DecimalFormat formatter = new DecimalFormat("#,###,###");
String yourFormattedString = formatter.format(100000);
try {
JSONObject Data = response.getJSONObject("Data");
JSONObject AggregatedData = Data.getJSONObject("AggregatedData");
try {
String Price = AggregatedData.getString("PRICE");
String formatPrice = formatter.format(Math.round(Float.valueOf(Price)));
_price.setText("Price :" + formatPrice);
} catch (Error e) {
_price.setText("Data Not Avvaliable");
}
try {
String Open = AggregatedData.getString("OPENDAY");
String formatOpen = formatter.format(Math.round(Float.valueOf(Open)));
_open.setText("Open :" + formatOpen);
} catch (Error e) {
_open.setText("Data Not Avvaliable");
}
try {
String Low = AggregatedData.getString("LOWDAY");
String formatLow = formatter.format(Math.round(Float.valueOf(Low)));
_low.setText("Low :" + formatLow);
} catch (Error e) {
_low.setText("Data Not Avvaliable");
}
try {
String High = AggregatedData.getString("HIGHDAY");
String formatHigh = formatter.format(Math.round(Float.valueOf(High)));
_high.setText("High :" + formatHigh);
} catch (Error e) {
_high.setText("Data Not Avvaliable");
}
try {
String Volume = AggregatedData.getString("VOLUMEDAY");
String formatVol = formatter.format(Math.round(Float.valueOf(Volume)));
_volume.setText("Volume :" + formatVol);
} catch (Error e) {
_volume.setText("Data Not Avvaliable");
}
try {
String LastUpdate = AggregatedData.getString("LASTUPDATE");
String convert = unix_time(Long.parseLong(LastUpdate));
_lastUpdate.setText("Last Update :" + LastUpdate);
} catch (Error e) {
_lastUpdate.setText("Data Not Avvaliable");
}
try {
String TradeId = AggregatedData.getString("LASTTRADEID");
_tradeId.setText("Trade Id :" + String.valueOf(Math.round(Float.parseFloat(TradeId))));
} catch (Error e) {
_tradeId.setText("Data Not Avvaliable");
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
requestQueue.add(jsonObjectRequest);
}
You can achieve this by using interface. Follow the below steps,
First create Interface in your application like,
public interface AsyncTaskListener {
void onRequestCompleted(JSONObject result, Integer statusCode);
}
And implement this interface in your activity where you want make request, Assume object of your volley class is objVolley, then your request will like below
public class YourActivity extends AppCompatActivity implements AsyncTaskListener {
public void priceDate(YourActivity.this, coin, YourActivity.this);
}
Then Your volley class and method like this,
public class PostDataHelper {
public void priceDate(Context contex, final String coin, final AsyncTaskListener asyncTaskListener) {
#Override
public void onResponse(JSONObject response) {
asyncTaskListener.onRequestCompleted(response, 200);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
asyncTaskListener.onRequestCompleted(response, 200);
}
});
}
}
Hope this will help you, Happy coding.
Your volley code is embedded into your activity code so there isn't much advantage to creating a interface.
You need to create a separate class for handling volley requests.
public class VolleyRequest {
VolleyCallback mResultCallback;
RequestQueue mRequestQueue;
public VolleyRequest(VolleyCallback resultCallback, Context context){
mResultCallback = resultCallback;
mRequestQueue = Volley.newRequestQueue(context);
}
public void cancelRequests(String TAG){
if(mRequestQueue != null){
mRequestQueue.cancelAll(TAG);
}
}
public void volleyGetRequest(String url, final String TAG) {
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET,
url, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
if (mResultCallback != null) {
mResultCallback.onSuccess(response, TAG);
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
if (mResultCallback != null) {
mResultCallback.onError(error, TAG);
}
}
});
jsonObjectRequest.setTag(TAG);
mRequestQueue.add(jsonObjectRequest);
}
}
Then create a interface class to handle the callbacks
public interface VolleyCallback {
void onSuccess(JSONObject response, String tag);
void onError(VolleyError error, String tag);
}
Then in your activity class
private void initvolley(){
VolleyCallback volleyCallback = new VolleyCallback() {
#Override
public void onSuccess(JSONObject response, String tag) {
switch (tag){
//add response handling code here
}
}
#Override
public void onError(VolleyError error, String tag) {
//handle error response here
}
};
VolleyRequest volleyRequest = new VolleyRequest(volleyCallback, this);
String URL = "https://min-api.cryptocompare.com/data/top/exchanges/full?fsym=BTC&tsym=USD&api_key=" + apiKey;
volleyRequest.volleyGetRequest(URL, request_tag/*Request tag incase you have multiple requests in same activity*/);
}

Wait for Volley to return an answer to update adapter

I am having trouble waiting for Volley's response before updating my RecyclerView's adapter. I am aware of the OnResponse method that the Request has, however, I have no way to pass the adapter as a parameter to it. Is there an easy way no notify my adapter that Volley has provided an answer?
private static JsonObjectRequest jsonReq = new JsonObjectRequest
(Request.Method.GET, espUrl, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
if (espVideos != null) {
espVideos.clear();
}
JSONArray jsonArray = response.getJSONArray("items");
for (int i = 0; i < jsonArray.length(); i++) {
String id = jsonArray.getJSONObject(i).getJSONObject("contentDetails").getString("videoId");
String title = jsonArray.getJSONObject(i).getJSONObject("snippet").getString("title");
espVideo = new YTVideo(id, title);
espVideos.add(espVideo);
}
SaveObject.saveYTVArray("espVideos", espVideos);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
public static void requestEspeciales(Activity act, ImageAdapterEspeciales adapter) {
Volley.newRequestQueue(act).add(jsonReq);
// I WANT TO CALL adapter.notifyDataSetChanged(); AFTER RESPONSE
}
EDIT:
I tried with a synchronize call but the page just freezes onCreate
synchronized (jsonReq) {
try {
jsonReq.wait();
} catch (InterruptedException e) {
Log.e("Error", e.toString());
}
Log.d("Notifying", espVideo.toString());
adapter.notifyDataSetChanged();
}
#Override
public void onResponse(JSONObject response) {
synchronized (jsonReq) {
try {
if (espVideos != null) {
espVideos.clear();
}
JSONArray jsonArray = response.getJSONArray("items");
for (int i = 0; i < jsonArray.length(); i++) {
String id = jsonArray.getJSONObject(i).getJSONObject("contentDetails").getString("videoId");
String title = jsonArray.getJSONObject(i).getJSONObject("snippet").getString("title");
String description = jsonArray.getJSONObject(i).getJSONObject("snippet").getString("description");
String thumbnailPath = jsonArray.getJSONObject(i).getJSONObject("snippet").getJSONObject("thumbnails").getJSONObject("high").getString("url");
String correspondingPlaylist = jsonArray.getJSONObject(i).getJSONObject("snippet").getString("playlistId");
espVideo = new YTVideo(id, title, description, thumbnailPath, correspondingPlaylist);
espVideos.add(espVideo);
}
SaveAndRetrieve.saveYTVArray("espVideos", espVideos);
Log.d("Retrieving", ((YTVideo) SaveAndRetrieve.getYTVArray("espVideos").get(0)).title);
notify();
} catch (JSONException e) {
e.printStackTrace();
}
}
}
I have no way to pass the adapter as a parameter to it.
You actually have two ways.
make the Adapter a final parameter of a method surrounding the Volley request. In other words, move the request from a static field and into a method.
More preferred, make the Adapter a member variable of the class
Both ways allow you to reference the adapter from within the onResponse method
Just set your recycler adapter inside your volleyresponse
#Override
public void onResponse(JSONObject response) {
synchronized (jsonReq) {
try {
if (espVideos != null) {
espVideos.clear();
}
JSONArray jsonArray = response.getJSONArray("items");
for (int i = 0; i < jsonArray.length(); i++) {
String id = jsonArray.getJSONObject(i).getJSONObject("contentDetails").getString("videoId");
String title = jsonArray.getJSONObject(i).getJSONObject("snippet").getString("title");
String description = jsonArray.getJSONObject(i).getJSONObject("snippet").getString("description");
String thumbnailPath = jsonArray.getJSONObject(i).getJSONObject("snippet").getJSONObject("thumbnails").getJSONObject("high").getString("url");
String correspondingPlaylist = jsonArray.getJSONObject(i).getJSONObject("snippet").getString("playlistId");
espVideo = new YTVideo(id, title, description, thumbnailPath, correspondingPlaylist);
espVideos.add(espVideo);
}
SaveAndRetrieve.saveYTVArray("espVideos", espVideos);
Log.d("Retrieving", ((YTVideo) SaveAndRetrieve.getYTVArray("espVideos").get(0)).title);
**YourAdapaterClass mAdapter = new YourAdapaterClass(youradapterdata);
recyclerview.setAdapter(mAdapter);**
notify();
} catch (JSONException e) {
e.printStackTrace();
}
}
}

Android Widget with asynctask

public class MainActivity extends AppWidgetProvider
{
TextView tv;
RemoteViews views;
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
super.onUpdate(context,appWidgetManager,appWidgetIds);
for(int i=0; i<appWidgetIds.length; i++){
int currentWidgetId = appWidgetIds[i];
views = new RemoteViews(context.getPackageName(),R.layout.activity_main);
appWidgetManager.updateAppWidget(currentWidgetId,views);
new PostTask().execute("url");
}
}
private class PostTask extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... params) {
String url = params[0];
// Dummy code
OkHttpClient client = new OkHttpClient();
client.setConnectTimeout(1, TimeUnit.MINUTES); // connect timeout
client.setReadTimeout(1, TimeUnit.MINUTES); // socket timeout
MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
RequestBody body = RequestBody.create(mediaType, "data=something");
Request request = new Request.Builder()
.url(url)
.post(body)
.addHeader("cache-control", "no-cache")
.addHeader("postman-token", "7a4d5df8-5aed-19bf-e1fb-c85f821c1d10")
.addHeader("content-type", "application/x-www-form-urlencoded")
.build();
Response response = null;
try {
response = client.newCall(request).execute();
return response.body().string();
} catch (Exception e1) {
e1.printStackTrace();
return e1.toString();
}
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
String data = "";
try {
JSONObject jsonRootObject = new JSONObject(result);
//Get the instance of JSONArray that contains JSONObjects
JSONArray jsonArray = jsonRootObject.optJSONArray("response_data");
//Iterate the jsonArray and print the info of JSONObjects
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
int id = Integer.parseInt(jsonObject.optString("CDRId").toString());
String name = jsonObject.optString("Status").toString();
data += "Agent : " + (i + 1) + "\nCDRId : " + id + " \n Status : " + name + " \n ";
}
views.setTextViewText(R.id.tv,data);
} catch (Exception e) {
views.setTextViewText(R.id.tv,e.toString());
}
}
}
}
I am trying to get a part of JSON(that I have parsed previously) in a widget. I am using AsyncTask to separate it from main thread and I am using OkHttpClient library to get JSON. I have class PostTask that gets me the parsed JSON. But can please anyone tell me how can I display it in the widget. This is the code.
Create a custom event, something like this:
public class MyEvent {
private String text;
public MyEvent(String text) {
this.text = text;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text= text;
}
}
Now at the place where you're posting the Event, simply create this custom Event with the json you want to send to your widget. (put this code in onPostExecute).
EventBus.getDefault().post(new MyEvent(result);
Now simply wherever your textView is, in Activity or Fragment, register the eventBus in onCreate:
EventBus.getDefault().register(this);
And create a method that listens for the event like this:
#Subscribe
public void onMyEvent(MyEvent myEvent){
String text = myEvent.getText();
//Now you can parse this text, if it's JSON, or you can simply set it
//to your textView or whatever
}

How do I get a value in an array into a void onclicklistener?

I am working on a project and below my code basically takes an array of objects and sets the Id to each object, However, when I click on my objects I would like to get that Id. I tried a local variable and I could only get the Id of the last object, how do I do this? I would like to get the value of String Answerid = currentQuestions.getString("id"); into my OnDown clicklistener.
mVolleySingleton = VolleySingleton.getInstance();
mRequestQueue = mVolleySingleton.getRequestQueue();
JsonArrayRequest request = new JsonArrayRequest(Request.Method.GET, URL_ANSWER, (String) null, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
listblogs = parseJSONResponseQuestion(response);
mAdapterQuestion.setBloglist(listblogs);
System.out.println(response);
System.out.println("it worked!!!");
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
System.out.println(error);
}
});
mRequestQueue.add(request);
}
String globalVar = " ";
private ArrayList<Blogs> parseJSONResponseQuestion(JSONArray response) {
if (!response.equals("")) {
ArrayList<Blogs> blogsArrayList = new ArrayList<>();
try {
StringBuilder data = new StringBuilder();
for (int i = 0; i < response.length(); i++) {
JSONObject currentQuestions = response.getJSONObject(i);
String text = currentQuestions.getString("text");
String questionId = currentQuestions.getString("questionId");
String votes = currentQuestions.getString("votes");
String Answerid = currentQuestions.getString("id");
System.out.println(response.length() + "length");
data.append(text + Answerid + "\n");
System.out.println(data);
Blogs blogs = new Blogs();
blogs.setMtext(text);
blogs.setVotes(votes);
blogs.setId(Answerid);
System.out.print(Answerid);
listblogs.add(blogs);
}
System.out.println(data.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
return listblogs;
}
public void OnDown(View view) {
System.out.println("VOTED Down");
final RequestQueue mrequestQueue = VolleySingleton.getInstance().getRequestQueue();
final String PUT_VOTE_UP = "someURL";
StringRequest PostVoteUp = new StringRequest(Request.Method.PUT, PUT_VOTE_UP, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
System.out.println(response + "reponse");
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
System.out.println("************Answer" + error + "error");
}
});
mrequestQueue.add(PostVoteUp);
System.out.println("VOTED DOWN");
}
}
Your click listener OnDown(View view) gets a view that was clicked. That's the only way you can identify what was clicked.
You should use View.getTag() to get the id:
Object obj = view.getTag();
The question is where can you add this code to set it:
View view = ...; // new View()?
view.setTag(object);

Categories

Resources