This question already has answers here:
android auto-refresh listview items
(2 answers)
Closed 4 years ago.
I have an android listview, but I have to relance the application every time that I want to refresh the list. I have two questions, please:
1) How to refresh it automatically?
2) How to do to receive a notification when an item is added to the database?
So it just tests if an item is added, I receive a notification, when I Click on it I will be able to see the list of items.
This is my code:
public class MainActivity extends Activity {
ListView SubjectFullFormListView;
ProgressBar progressBar;
String HttpURL = "http://254.221.325.11/test/Subject.php";
ListAdapter adapter ;
List<Subject> SubjectFullFormList;
EditText editText ;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
SubjectFullFormListView = (ListView) findViewById(R.id.SubjectFullFormListView);
editText = (EditText)findViewById(R.id.edittext1);
progressBar = (ProgressBar) findViewById(R.id.ProgressBar1);
new ParseJSonDataClass(this).execute();
}
private class ParseJSonDataClass extends AsyncTask<Void, Void, Void> {
public Context context;
String FinalJSonResult;
public ParseJSonDataClass(Context context) {
this.context = context;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... arg0) {
HttpServiceClass httpServiceClass = new HttpServiceClass(HttpURL);
try {
httpServiceClass.ExecutePostRequest();
if (httpServiceClass.getResponseCode() == 200) {
FinalJSonResult = httpServiceClass.getResponse();
if (FinalJSonResult != null) {
JSONArray jsonArray = null;
try {
jsonArray = new JSONArray(FinalJSonResult);
JSONObject jsonObject;
Subject subject;
SubjectFullFormList = new ArrayList<Subject>();
for (int i = 0; i < jsonArray.length(); i++) {
subject = new Subject();
jsonObject = jsonArray.getJSONObject(i);
subject.Subject_Name = jsonObject.getString("SubjectName");
subject.Subject_Full_Form = jsonObject.getString("SubjectFullForm");
SubjectFullFormList.add(subject);
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} else {
Toast.makeText(context, httpServiceClass.getErrorMessage(), Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result)
{
progressBar.setVisibility(View.GONE);
SubjectFullFormListView.setVisibility(View.VISIBLE);
adapter = new ListAdapter(SubjectFullFormList, context);
SubjectFullFormListView.setAdapter(adapter);
}
}
}
I find a solution but I don't know how and where to insert it:
final Handler handler = new Handler();
Runnable refresh = new Runnable() {
#Override
public void run() {
new JSONParse().execute();
handler.postDelayed(this, 60 * 1000);
}
};
handler.postDelayed(refresh, 60 * 1000);
Thank you.
-> Write a runnable thread which calls the API of the list regularly after some time and on its response change the list in the adapter and call notifydatasetchanged().
-> By using FCM you can get the solution to question 2. When an item is added in DB generate a notification from server side and send it to clients sides and by using pending intent you can show the list when user tap on the notification.
(OR)
-> You can use the real-time DB Like Firebase DB or Realm etc. for this approach. This DB notify you when an item added to the list and you don't need threads to refresh list.
Related
I'm making app which get server data from mvc spring server.
If client login success in main Activity, app try to get data from server, and use list view show data in next activity.
It works clear in first login, but when I turn back on main Activity, and try login again, next activity doesn't show anything.
I used logs to find problem and I found that when client login again, next activity's onCreate() and onResume() works too fast. My app uses thread and get data from server, logs says after onCreate and onResume works and my thread get data from server.
So this is my problem
1 App uses thread to get data from server
2 First try works but after thread is too late than onResume and onCreate in activity
3 should I have to make thread more fast? or use flags or something make onCreate and onResume works after thread works end? or does my code have problems?
This is my activity which show data from server
public class ServerListActivity extends AppCompatActivity {
public static ArrayList<ServerListItem> serverListItemArrayList;
public static ArrayList<ServerListItem> scrollEventServerListItemList;
public TextView serverListInfoTextView;
private ProgressBar progressBar;
private boolean lockListView;
private boolean isThisLastItemVisibleFlag;
private ServerListViewAdapter serverListViewAdapter;
private int currentPageNum;
public Handler msgHandler;
#Override
protected void onCreate(Bundle savedInstanceState) {
lockListView = false; // scroll event
currentPageNum = 0; // scroll event
isThisLastItemVisibleFlag = false; // scroll event
scrollEventServerListItemList = new ArrayList<>();
serverListItemArrayList = new ArrayList<>();
msgHandler = new Handler();
super.onCreate(savedInstanceState);
ServerListManager serverListManager = new ServerListManager(msgHandler);
serverListManager.getServerList();
setContentView(R.layout.activity_server_list);
ImageButton turnBackBtn = findViewById(R.id.turn_back_btn);
serverListInfoTextView = findViewById(R.id.server_list_Info);
ListView serverListView = findViewById(R.id.server_list_view);
progressBar = findViewById(R.id.progressBar);
serverListViewAdapter = new ServerListViewAdapter(scrollEventServerListItemList, R.layout.server_list_item, getApplicationContext());
serverListView.setAdapter(serverListViewAdapter);
progressBar.setVisibility(View.GONE);
serverListView.setTranscriptMode(ListView.TRANSCRIPT_MODE_NORMAL);
System.out.println(serverListItemArrayList.size());
setServerListInfo(serverListItemArrayList);
and this is my thread
public class ServerListManager {
private final static int SERVER_PROBLEM = 666;
private Handler handler;
public ServerListManager(Handler handler) {
this.handler = handler;
}
public void getServerList() {
new Thread(new Runnable() {
#Override
public void run() {
HttpURLConnection connection = null;
StringBuilder stringBuffer = new StringBuilder();
try {
URL url = new URL("my ip and blah balh");
connection = (HttpURLConnection) url.openConnection();
} catch (IOException e) {
e.printStackTrace();
}
if (connection != null) {
connection.setConnectTimeout(5000);
connection.setUseCaches(false);
try {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"));
String line = bufferedReader.readLine();
if (!"".equals(line)) {
stringBuffer.append(line);
Log.i("ServerListManager", stringBuffer.toString());
}
setServerListItem(stringBuffer.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
}
}).start();
}
private void setServerListItem(String dataFromServer) {
Log.i("ServerListManager", "setServerListItem() works ");
ArrayList<ServerListItem> serverListItems = new ArrayList<>();
JsonParser jsonParser = new JsonParser();
JsonObject jsonObjectFirst = (JsonObject) jsonParser.parse(dataFromServer);
if (!String.valueOf(jsonObjectFirst.get("status")).equals("\"200\"")) {
Message message = new Message();
message.what = SERVER_PROBLEM;
handler.sendMessage(message);
} else {
String serverListJsonVersion = String.valueOf(jsonObjectFirst.get("serverModelList"));
JsonArray jsonArray = (JsonArray) jsonParser.parse(serverListJsonVersion);
Gson gson = new Gson();
for (JsonElement jsonElement : jsonArray) {
ServerListItem serverListItem = gson.fromJson(jsonElement, ServerListItem.class);
serverListItems.add(serverListItem);
}
ServerListActivity.serverListItemArrayList = serverListItems;
}
}
You can try using AsyncTask
private class AsyncCaller extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
//this method will be running on UI thread
//can call progress bar here to show loading process
}
#Override
protected Void doInBackground(Void... params) {
//this method will be running on background thread
//so don't update UI from here
//do your long running http tasks here,
//you don't want to pass argument and you
//can access the parent class' variable url over here
// call your server data here
serverListManager.getServerList();
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
//this method will be running on UI thread
//Show the result obtained from doInBackground
//this executed after doInBackground so after you get data from doInBackground
//you can set your adapter here
}
}
Then you can execute AsyncTask like this
new AsyncCaller().execute();
So, I have this assignment at school where I have to make in Android Studio an app that manages daily tasks,basically a calendar, but the activities are saved in a server with JSON format. The problem is that I have a list of all activities in a day in a RecyclerView and I have to have a button for each activity that allows me to delete it from the server and I have no idea how can I do that, I mean, when I delete an activity i have to do it with its ID.
I currently have an app that works but i have to add that functionality, i have an Activity that has a recyclerView and shows the name of the task, the start and finish time and a button.I don't know if I can put the task ID in a hidden field so I can use that or is there a better way to do it.
I'm new with Android programming, so its kinda confusing.
This is the code that I use to get the JSON data.
public class dayActivities extends AppCompatActivity {
private RecyclerView mRecyclerView;
private JsonManager json;
ArrayList<Tarea> list;
RequestQueue requestQueue;
String url="http://186.16.12.200:3000/agenda1";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_day_activities);
Bundle b = getIntent().getExtras();
String date = b.getString("fecha");
setTitle(getDate(date));
requestQueue= Volley.newRequestQueue(getApplicationContext());;
mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
mRecyclerView.setHasFixedSize(true);
LinearLayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(layoutManager);
this.getData(date);
}
public void getData(String date){
list=new ArrayList<Tarea>();
JsonArrayRequest arrReq = new JsonArrayRequest(Request.Method.GET, url + "?fecha=" + date,null,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
if (response.length() > 0) {
// The user does have repos, so let's loop through them all.
for (int i = 0; i < response.length(); i++) {
try {
// For each repo, add a new line to our repo list.
JSONObject jsonObj = response.getJSONObject(i);
Integer id = (Integer) jsonObj.get("id");
String actividad = jsonObj.get("actividad").toString();
String fecha = jsonObj.get("fecha").toString();
String inicio = jsonObj.get("horaInicio").toString();
String fin = jsonObj.get("horaFin").toString();
list.add(new Tarea(id,actividad,fecha,inicio,fin));
} catch (JSONException e) {
// If there is an error then output this to the logs.
Log.e("Volley", "Invalid JSON Object.");
}
}
mRecyclerView.setAdapter(new Adaptador(list));
} else {
// The user didn't have any repos.
Log.e("Volley", "Not found");
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("Volley", error.toString());
error.printStackTrace();
}
});
// Add the request we just defined to our request queue.
// The request queue will automatically handle the request as soon as it can.
requestQueue.add(arrReq);
}
public String getDate(String fecha){
String meses[]={"Enero","Febrero","Marzo","Abril","Mayo","Junio","Julio","Agosto,","Septiembre","Octubre","Noviembre","Diciembre"};
return fecha.substring(6)+" de "+meses[Integer.parseInt(fecha.substring(4,6))-1]+" del "+fecha.substring(0,4);
}
}
I'm loading my markers(clustering) from a json and it's working.
But the markers is not so fast to render. My solution is show the progressbar while the markers is loading.
But the problem is that the progressbar is gone before the render.
I'm using the AsyncTask to render and I am adding the marker in the onProgressUpdate.
public class GetMarkersAsync extends AsyncTask<String, HistoricoTO, List<HistoricoTO>> {
private final static String OBTER = "http://10.0.0.65/Service.asmx/getEnvios";
GoogleMap map;
private Activity activity;
private ProgressBar progressBar;
public GetMarkersAsync (GoogleMap map, Activity activity) {
this.map = map;
this.activity = activity;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
progressBar = (ProgressBar) activity.findViewById(R.id.progressBar1);
progressBar.setIndeterminate(true);
progressBar.setVisibility(View.VISIBLE);
}
#Override
protected List<HistoricoTO> doInBackground(String... params) {
WebService ws = new WebService();
String response = ws.makeRequest(OBTER);
List<HistoricoTO> listaHistoricos = new ArrayList<HistoricoTO>();
try {
JSONArray array = new JSONArray(response);
HistoricoTO historico;
JSONObject jsonObject;
for (int i = 0; i < array.length(); i++) {
jsonObject = array.getJSONObject(i);
historico = new HistoricoTO();
historico.setName(jsonObject.getString("name"));
historico.setLatitude(jsonObject.getDouble("latitude"));
historico.setLongitude(jsonObject.getDouble("longitude"));
listaHistoricos.add(historico);
publishProgress(historico);
}
} catch (JSONException e) {
e.printStackTrace();
}
return listaHistoricos;
}
#Override
protected void onProgressUpdate(HistoricoTO... historicos) {
super.onProgressUpdate(historicos);
drawMarker(this.map, historicos[0]);
}
#Override
protected void onPostExecute(List<HistoricoTO> historicoTOs) {
super.onPostExecute(historicoTOs);
progressBar.setVisibility(View.GONE)
}
private void drawMarker(GoogleMap gmap, HistoricoTO historicoTO)
{
MyItem offsetItem = new MyItem(historicoTO.getLatitude(), historicoTO.getLongitude(), historicoTO);
MainActivity.mClusterManager.getMarkerCollection().addMarker(mo);
MainActivity.mClusterManager.addItem(offsetItem);
gmap.addMarker(mo);
}
}
PS: It's working, the ProgressBar is showing, but the problem is that the markers only shows when I "move" the map ou touch.
every time you add a new marker, invalidate map again.
so it will draw your item on map.
map.invalidate()
I've a RecyclerView, Async Task, Json File .
What i want :
Get the Json and add an item for every loop .
My problem :
I'm getting the json, and looping, But the "List.add(Item)" isn't adding any line, So the recycler is empty .
Code :
Adapter RcAdapter;
public static List<CatItem> Items;
String DATA_URL;
#SuppressLint("InflateParams")
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinLayout = (LinearLayout) inflater.inflate(R.layout.cat_recycler,
container, false);
setHasOptionsMenu(true);
DATA_URL = this.getArguments().getString(MainActivity.DATA);
initListViews();
return LinLayout;
}
private void initListViews() {
List<CatItem> rowListItem = getAllItemList();
LinearLayoutManager gridLayout = new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false);
RecyclerView RcView = (RecyclerView) LinLayout.findViewById(R.id.cat_rv);
RcView.setHasFixedSize(true);
RcView.setLayoutManager(gridLayout);
RcAdapter = new Adapter(getActivity(), rowListItem);
RcView.setAdapter(RcAdapter);
}
private List<CatItem> getAllItemList() {
Items = new ArrayList<>();
new GetDevices().execute(DATA_URL);
return Items;
}
class GetDevices extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(getActivity());
pDialog.setMessage("Loading Devices, Please Wait..");
pDialog.setIndeterminate(false);
pDialog.setCancelable(true);
pDialog.show();
}
protected String doInBackground(String... params) {
return JsonUtils.getJSONString(params[0]);
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if(pDialog != null)
pDialog.dismiss();
if(result == null){
Toast.makeText(getActivity(),"Failed To Fetch Data, Please Refresh",Toast.LENGTH_LONG).show();
} else {
try {
JSONObject MainJSON = new JSONObject(result);
JSONArray DevicesArrays = MainJSON.getJSONArray("roms_center");
for (int i = 0; i < DevicesArrays.length() ; i++){
CatItem Item = new CatItem();
JSONObject first = DevicesArrays.getJSONObject(i);
Log.LogInfo("I'm In Position " + i);
Item.setDevice_Name(first.getString("device_name"));
Item.setTotal_Downloads(first.getInt("roms_count"));
Item.setDevice_ID(first.getInt("device_id"));
Items.add(Item);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
What's the problem ?
Also, In my holder i've implemented OnClick, and i want to get something from the pressed position, I'm using the following way :
Main.Items.get(getLayoutPosition()).getDevice_ID()
As you can see, I'm getting the static List, Any better way to achieve this ?
The program flow between these two lines is not what you think it is.
new GetDevices().execute(DATA_URL);
return Items;
GetDevices is an AsyncTask, which means it will run asynchronously.
The return statement in the next line will not wait for the async task to finish, and it returns null because async task takes time to finish.
After you've added an item to your list you have to tell your adapter about it. So you could do it in two ways:
RcAdapter.notifyItemInserted(Items.size() - 1);
or
RcAdapter.notifyDataChanged();
I'm having trouble with the way I am trying to get the progress dialogue to work.
First I initialise the progress dialogue in my searchable activity class as so:
ProgressDialog pd;
Then I show the progress dialogue when a search is executed in my dosearch method:
public void doSearch(String query) {
pd = ProgressDialog.show(SearchableActivity.this, "Last Fm", "Searching Tracks...");
String[] result = new String[] {"searching..."};
AlbumSearchService service = new AlbumSearchService(query);
service.addListener(this);
thread = new Thread(service);
thread.start();
setListAdapter(new ArrayAdapter<String> (this ,
R.layout.album_list_cell,
R.id.text,
result));
Log.v("blah", "doSearch was called");
service.run();
}
And finally, once the search is complete, I dismiss the progress indicator in my service complete method.
pd.dismiss();
I fail to see what I'm doing wrong, whenever I commence a search, the progress dialogue feature does not appear please help :(
Thank you!
Edit:
Here's my full code for those with a sharp eye. I think it may be a thread issue but i have no clue.
public class SearchableActivity extends ListActivity implements ServiceListener {
private Thread thread;
private ArrayList searchResults;
ProgressDialog pd;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.search);
searchResults = new ArrayList<JSONObject>(); // initialise array list to
// hold the results so
// we can do something
// with them
// this gets the intent being sent over
Intent intent = getIntent();
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
String query = intent.getStringExtra(SearchManager.QUERY);
doSearch(query);
}
}
#Override
// this method handles what happens when a user clicks a result.
// the search item is broadcasted for other people to use.
protected void onListItemClick(ListView l, View v, int position, long id) {
if (position < searchResults.size()) { // if the position is less than
// the size of the results array
// then...
Intent result = new Intent(); // create a new intent called result.
result.setAction(SEARCH_BROADCAST); // place the broadcast message
// on the intent.
result.putExtra("result", searchResults.get(position).toString()); // add
// extended
// data
// to
// the
// intent
this.sendBroadcast(result);
this.finish();
}
}
public void doSearch(String query) {
pd = ProgressDialog.show(SearchableActivity.this, "Last Fm",
"Searching Tracks...");
String[] result = new String[] { "searching..." };
AlbumSearchService service = new AlbumSearchService(query);
service.addListener(this);
thread = new Thread(service);
thread.start();
setListAdapter(new ArrayAdapter<String>(this, R.layout.album_list_cell,
R.id.text, result));
Log.v("blah", "doSearch was called");
service.run();
}
public void ServiceComplete(AbstractService service) {
if (pd.isShowing()) {
pd.dismiss();
}
if (!service.hasError()) {
AlbumSearchService albumService = (AlbumSearchService) service;
String[] result = new String[albumService.getResults().length()];
searchResults.clear();
for (int i = 0; i < albumService.getResults().length(); i++) {
try {
searchResults.add(albumService.getResults()
.getJSONObject(i)); // gets the json object for each
// result and adds to array
result[i] = albumService.getResults().getJSONObject(i)
.getString("name");
} catch (JSONException ex) {
result[i] = "Error";
}
}
setListAdapter(new ArrayAdapter<String>(this,
R.layout.album_list_cell, R.id.text, result));
} else {
String[] result = new String[] { "No Results" };
setListAdapter(new ArrayAdapter<String>(this,
R.layout.album_list_cell, R.id.text, result));
}
}
public static final String SEARCH_BROADCAST = "search_result_selected";
}