I developed an android application in which I want to get data from the database without refreshing the app. I tried different methods but no one works for me. I am using PHP for fetching data from the database into my android app. Below is my code which is for now only fetching data from a database but I have to refresh the app if I update data in the database to get the updated value in the app. I want realtime values from the database, like, if I update data in the database, I want the same update in the app but without refreshing it.
public class Profile extends AppCompatActivity implements View.OnClickListener {
private TextView textViewUsername,textViewHr,textViewBp;
private Button button;
private ProgressDialog progressDialog;
private SwipeRefreshLayout swipeRefreshLayout;
private ImageView imageViewWet, imageViewTempered;
String username;
private static int wet,tempered;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_profile2);
username = SharedPrefManager.getInstance(this).getUsername();
textViewUsername = (TextView) findViewById(R.id.pUsername);
textViewHr = (TextView) findViewById(R.id.heartRate);
textViewBp = (TextView) findViewById(R.id.bloodPressure);
swipeRefreshLayout = findViewById(R.id.swipeToRefresh);
imageViewTempered = (ImageView) findViewById(R.id.imageViewTempered);
imageViewWet =(ImageView) findViewById(R.id.imageViewWet);
button = (Button) findViewById(R.id.refresh);
wet = SharedPrefManager.getInstance(getApplicationContext()).getWetStatus();
tempered = SharedPrefManager.getInstance(getApplicationContext()).getTemperedStatus();
textViewUsername.setText(SharedPrefManager.getInstance(this).getUsername());
textViewHr.setText(String.valueOf(SharedPrefManager.getInstance(this).getHeartRate()));
textViewBp.setText(String.valueOf(SharedPrefManager.getInstance(this).getTemperature()));
if(wet==1){
imageViewWet.setImageResource(R.drawable.tick);
}
else{
imageViewWet.setImageResource(R.drawable.cross);
}
if(tempered == 1){
imageViewTempered.setImageResource(R.drawable.tick);
}
else{
imageViewTempered.setImageResource(R.drawable.cross);
}
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
data();
swipeRefreshLayout.setRefreshing(false);
}
});
button.setOnClickListener(this);
/*if(!SharedPrefManager.getInstance(this).isLoggedIn()){
finish();
startActivity(new Intent(this,ProfileActivity.class));
return;
}*/
progressDialog = new ProgressDialog(this);
progressDialog.setMessage("Please Wait...");
}
public void data(){
progressDialog.show();
StringRequest stringRequest = new StringRequest(Request.Method.POST, Constants.URL_DATA,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
progressDialog.dismiss();
try {
JSONObject obj = new JSONObject(response);
if(!obj.getBoolean("error")){
System.out.println("IN SHARED SET VALES");
SharedPrefManager.getInstance(getApplicationContext()).data(obj.getInt("Id"),obj.getString("Username"),obj.getInt("Heart_Rate"),obj.getInt("Temperature"),obj.getInt("Wet"),obj.getInt("Tempered"));
textViewUsername.setText(SharedPrefManager.getInstance(getApplicationContext()).getUsername());
textViewHr.setText(String.valueOf(SharedPrefManager.getInstance(getApplicationContext()).getHeartRate()));
textViewBp.setText(String.valueOf(SharedPrefManager.getInstance(getApplicationContext()).getTemperature()));
wet = SharedPrefManager.getInstance(getApplicationContext()).getWetStatus();
tempered = SharedPrefManager.getInstance(getApplicationContext()).getTemperedStatus();
if(wet==1){
imageViewWet.setImageResource(R.drawable.tick);
}
else{
imageViewWet.setImageResource(R.drawable.cross);
}
if(tempered == 1){
imageViewTempered.setImageResource(R.drawable.tick);
}
else{
imageViewTempered.setImageResource(R.drawable.cross);
}
}else{
Toast.makeText(getApplicationContext(),obj.getString("message"),Toast.LENGTH_LONG).show();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
progressDialog.dismiss();
Toast.makeText(getApplicationContext(),error.getMessage(),Toast.LENGTH_LONG).show();
}
}
){
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String,String> params = new HashMap<>();
params.put("Username",username);
return params;
}
};
RequestHandler.getInstance(this).addToRequestQueue(stringRequest);
}
#Override
public void onClick(View v) {
if(v == button){
data();
}
}
}
Below is the layout of my app. Basically I want to update Heart Rate and Temperature continuously without refreshing the app.
Please help me, how I can get data from the database into my app without refreshing the app?
Thanks in Advance
Try using reactive programming tools like RxJava or RxAndroid. Reactive Programming is basically event-based asynchronous programming.
Use time Outs to automatically refresh the content after few minutes .
Server Side app rendering and sockets could also be useful for such cases.
Related
help guys how to display image without using a button, I tried to put it on create but not working and I tried to make it as a function but still not working,but when in button (on click) it show image. I want to show the image without clicking the button.
I want to load the image without clicking the button, so when the user come the image automatically load without push of a button.
public class MainActivity extends AppCompatActivity {
TextView textViewdatashow;
EditText editTextvalue;
ImageView imageView;
Button buttonfetch;
String url ;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textViewdatashow = (TextView) findViewById(R.id.tvshowdata);
editTextvalue = (EditText) findViewById(R.id.etvalue);
imageView = (ImageView) findViewById(R.id.image);
buttonfetch = (Button) findViewById(R.id.buttonfetchdata);
buttonfetch.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String id = editTextvalue.getText().toString();
url = "https://PASTE_YOUR_IMAGE_URL"+id+".jpg";
getData();
}
});
}
private void getData() {
String id = editTextvalue.getText().toString().trim();
if (id.equals("")) {
Toast.makeText(this, "Check Detail!", Toast.LENGTH_LONG).show();
return;
}
String url = Config.DATA_URL + editTextvalue.getText().toString().trim();
StringRequest stringRequest = new StringRequest(url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
showJSONS(response);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(MainActivity.this, error.getMessage().toString(), Toast.LENGTH_LONG).show();
}
});
RequestQueue requestQueue = Volley.newRequestQueue(this);
requestQueue.add(stringRequest);
}
private void showJSONS(String response) {
String name = "";
try {
JSONObject jsonObject = new JSONObject(response);
JSONArray result = jsonObject.getJSONArray(Config.JSON_ARRAY);
JSONObject collegeData = result.getJSONObject(0);
name = collegeData.getString(Config.KEY_NAME);
} catch (JSONException e) {
e.printStackTrace();
}
textViewdatashow.setText("" + name);
ImageRetriveWithPicasso();
}
private void ImageRetriveWithPicasso() {
Picasso.get()
.load(url)
.placeholder(R.drawable.imageholder)
.into(imageView);
}
}
Put this code inside on create view
final Handler myHandler = new
Handler(Looper.getMainLooper());
new Thread(new Runnable() {
#Override
public void run() {
myHandler.post(new Runnable() {
#Override
public void run() {
getData()
}
});
}
})).start();
}
I am trying to use realm database to display my api data. I want to display the company name, however the data is saids it is inserted in the log but cant seem to display the data on the UI. Here is the code..
Any help would be greatly appreciated with this problem. The variables are at the top and the problem is when it hits on success, ive written the code "write to DB", but it doesnt display the data but tells me the data has been inserted.
// Variables for the search input field and results TextViews.
private EditText mCompanyInput;
private TextView mTitleText;
private TextView mDescriptionText;
private TextView mOfficerText;
private TextView mTitleText1;
private TextView mDescriptionText1;
private OkHttpClient okHttpClient;
private static final String TAG = "MainActivity";
private Request request;
private String url = "https://api.companieshouse.gov.uk/search/companies?q=";
Button save;
TextView log;
Realm realm;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mCompanyInput = findViewById(R.id.companyInput);
log = findViewById(R.id.log);
mDescriptionText = findViewById(R.id.descriptionText);
mOfficerText = findViewById(R.id.officerText);
mTitleText1 = findViewById(R.id.titleText1);
mTitleText = findViewById(R.id.titleText);
mDescriptionText1 = findViewById(R.id.descriptionText1);
save = findViewById(R.id.searchButton);
realm = Realm.getDefaultInstance();
save.setOnClickListener(this);
}
public void onClick(View view){
okHttpClient = new OkHttpClient();
request = new Request.Builder().url(url).header("Authorization", "k6DNRbTp-AnQWn51JBz5VuPiTl8jv4_etdzoMyhf") .method("GET", null).build();
Log.d(TAG, "onClick:"+url);
okHttpClient.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
Log.i(TAG, e.getMessage());
}
#Override
public void onResponse(Call call, Response response) throws IOException {
Log.i(TAG,response.body().string());
Log.d(TAG, "onResponse:"+response.code());
}
});
writeToDB(mCompanyInput.getText().toString().trim(), (mDescriptionText.getText().toString().trim()));
showData();
}
public void showData(){
RealmResults<Company> guests = realm.where(Company.class).findAll();
// Use an iterator to invite all guests
String op="";
for (Company guest : guests) {
op+=guest.getName();
op+=guest.getAppointments();
}
log.setText(op);
}
public void writeToDB(final String mTitleText1, final String mDescriptionText1){
realm.executeTransactionAsync(new Realm.Transaction() {
#Override
public void execute(Realm bgRealm) {
Company user = new Company(mTitleText1, mDescriptionText1);
bgRealm.insert(user);
}
}, new Realm.Transaction.OnSuccess() {
#Override
public void onSuccess() {
writeToDB(mCompanyInput.getText().toString().trim(), (mOfficerText.getText().toString().trim()));
showData();
// Transaction was a success.
Log.v("Database", "Data Inserted");
}
}, new Realm.Transaction.OnError() {
#Override
public void onError(Throwable error) {
// Transaction failed and was automatically canceled.
Log.e("Database", error.getMessage());
}
});
}
#Override
protected void onDestroy() {
super.onDestroy();
realm.close();
}
Why are you calling writeToDB() from the onSuccess() method? This will cause recursion and keep writing the same data into the realm. It's correct to call showData() from onSuccess(), but there's not much point calling it directly from onClick().
I think your problem though is that you're trying to update the UI from a thread: it's called from an async transaction thread and not the main thread. See this answer (and there are others you can find easily once you know the problem: Updating UI / runOnUiThread / final variables: How to write lean code that does UI updating when called from another Thread.
all of you great developers, which I'm not, since I'm posting this question ;-)
I have a site with a to-do list where you can log in to Google. Now I want to make an Android app to access my DB on my site. I have the login with Google part correct and from that login activity, I switch to the activity (via intent, that's how I know I'm logged in correctly, cause the intent is only started when logged in) to display my to-do list. This is where I'm stuck. I can't seem to fetch the data from the DB, even though I'm logged in. I searched a bit online (watched a few hours of youtube video on the topic, and also searched StackOverflow, the internet in general and the Google developer pages), but no result. I'm guessing I have to pass on the token from the login activity to the other, but other than that, I just don't know and I'm hoping someone of you can point me in the right direction. Extra info: site is written in PHP with PDO for DB functions and MySQL DB. I also managed to get the JSON output on the site. In the android app, I also use Volley and it's written in Java (not Kotlin). I would really appreciate the help and if you need more info (or maybe a part of the code), be sure to ask.
Regards
Christophe
Edit: hereby the requested code:
LoginActivity:
package package_name;
some imports...
public class LoginActivity extends AppCompatActivity {
private static final String TAG = "Scorpio To Do Login: ";
GoogleSignInOptions gso;
GoogleSignInClient mGoogleSignInClient;
SignInButton signInButton;
private int RC_SIGN_IN = 6;
private static final String URL_DATA = "https://some.url.be";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
// Configure sign-in to request the user's ID, email address, and basic
// profile. ID and basic profile are included in DEFAULT_SIGN_IN.
gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(getString(R.string.server_client_id))
.requestEmail()
.build();
// Build a GoogleSignInClient with the options specified by gso.
mGoogleSignInClient = GoogleSignIn.getClient(this, gso);
}
#Override
protected void onStart() {
super.onStart();
// Check for existing Google Sign In account, if the user is already signed in
// the GoogleSignInAccount will be non-null.
GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(this);
updateUI(account);
}
private void updateUI(GoogleSignInAccount account) {
Log.w(TAG, "account = " + account);
if(account == null){
// Set the dimensions of the sign-in button.
signInButton = findViewById(R.id.sign_in_button);
signInButton.setSize(SignInButton.SIZE_WIDE);
signInButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
signIn();
}
});
signInButton.setVisibility(View.VISIBLE);
} else {
Context context = LoginActivity.this;
/* This is the class that we want to start (and open) when the button is clicked. */
Class destinationActivity = TaskActivity.class;
/*
* Here, we create the Intent that will start the Activity we specified above in
* the destinationActivity variable. The constructor for an Intent also requires a
* context, which we stored in the variable named "context".
*/
Intent startChildActivityIntent = new Intent(context, destinationActivity);
/*
* Once the Intent has been created, we can use Activity's method, "startActivity"
* to start the ChildActivity.
*/
startActivity(startChildActivityIntent);
}
}
private void signIn() {
Intent signInIntent = mGoogleSignInClient.getSignInIntent();
startActivityForResult(signInIntent, RC_SIGN_IN);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Result returned from launching the Intent from GoogleSignInClient.getSignInIntent(...);
if (requestCode == RC_SIGN_IN) {
// The Task returned from this call is always completed, no need to attach
// a listener.
Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
handleSignInResult(task);
}
}
private void handleSignInResult(Task<GoogleSignInAccount> completedTask) {
try {
GoogleSignInAccount account = completedTask.getResult(ApiException.class);
String idToken = account.getIdToken();
Log.d("Token: ", idToken);
// Signed in successfully, show authenticated UI.
updateUI(account);
} catch (ApiException e) {
// The ApiException status code indicates the detailed failure reason.
// Please refer to the GoogleSignInStatusCodes class reference for more information.
Log.w(TAG, "signInResult:failed code=" + e.getStatusCode());
updateUI(null);
}
}
}
TaskActivity:
package package_name;
some imports...
public class TaskActivity extends AppCompatActivity {
private static final String URL_DATA = "https://some.url.be";
private RecyclerView recyclerView;
private RecyclerView.Adapter scorpioAdapter;
private List<ListItem> listItems;
String JSON_STRING;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_task);
recyclerView = findViewById(R.id.rv);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
listItems = new ArrayList<>();
}
/*REAL DATA*/
/*try instead of loadRecyclerViewData*/
public void getJSON(View view){
new BackgroundTask().execute();
}
/*end try*/
private void loadRecyclerViewData() {
final ProgressDialog progressDialog = new ProgressDialog(this);
progressDialog.setMessage("Loading data...");
progressDialog.show();
StringRequest stringRequest = new StringRequest(Request.Method.GET,
URL_DATA,
new Response.Listener<String>() {
#Override
public void onResponse(String s) {
progressDialog.dismiss();
try {
JSONArray jsonArray = new JSONArray(s);
for(int i=0;i<jsonArray.length();i++){
JSONObject o = jsonArray.getJSONObject(i);
int id = o.getInt("id");
String name = o.getString("name");
int done = o.getInt("done");
String reminderDate = o.getString("reminderdate");
String reminderTime = o.getString("remindertime");
ListItem item = new ListItem(id, name, done, reminderDate, reminderTime);
listItems.add(item);
}
scorpioAdapter = new ScorpioAdapter(listItems, getApplicationContext());
recyclerView.setAdapter(scorpioAdapter);
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError volleyError) {
Toast.makeText(getApplicationContext(), volleyError.getMessage(), Toast.LENGTH_LONG).show();
}
}
);
RequestQueue requestQueue = Volley.newRequestQueue(this);
requestQueue.add(stringRequest);
}
/*END REAL DATA*/
/* things I tried*/
class BackgroundTask extends AsyncTask<Void, Void, String> {
String json_url;
#Override
protected void onPreExecute() {
json_url = "https://some.url.be";
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
#Override
protected void onPostExecute(String result) {
Log.i("Scorpio To Do: ", result);
TextView name = (TextView) findViewById(R.id.name);
name.setText(result);
}
#Override
protected String doInBackground(Void... voids) {
try {
URL url = new URL(json_url);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
InputStream inputStream = httpURLConnection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder stringBuilder = new StringBuilder();
while ((JSON_STRING = bufferedReader.readLine()) != null){
stringBuilder.append(JSON_STRING + "\n");
}
bufferedReader.close();
inputStream.close();
httpURLConnection.disconnect();
return stringBuilder.toString().trim();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
/*end try*/
}
I have an authentication interface with an email field and a button.
When i click the button an AsyncTask should verify if the email exist in a google app engine datastore or not.
This is the code for my asyncTask:
public class ConnexionAsyncTask extends AsyncTask<Object, Object, Inscrit> {
private static InscritApi inscritApi = null;
private Context context;
String email;
ProgressDialog dialog;
public ConnexionAsyncTask(Context context, String email) {
this.context = context;
dialog = new ProgressDialog(context);
this.email = email;
}
#Override
protected void onPreExecute() {
dialog.setMessage("Connexion en cours");
dialog.setIndeterminate(true);
dialog.setCancelable(false);
dialog.show();
}
#Override
protected Inscrit doInBackground(Object... params) {
if (inscritApi == null) {
InscritApi.Builder builder = new InscritApi.Builder(AndroidHttp.newCompatibleTransport(), new AndroidJsonFactory(), null)
.setRootUrl( // some url );
inscritApi = builder.build();
}
try {
return inscritApi.get(email).execute();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Inscrit inscrit) {
MainActivity main = (MainActivity) context;
main.setInscrit(inscrit);
dialog.dismiss();
}}
And this is the MainActivity code:
public class MainActivity extends AppCompatActivity {
Inscrit inscrit;
Button btncnx;
EditText emailcnx;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btncnx = (Button) findViewById(R.id.btncnx);
emailcnx = (EditText) findViewById(R.id.emailcnx);
btncnx.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
ConnexionAsyncTask task = new ConnexionAsyncTask(MainActivity.this, emailcnx.getText().toString());
task.execute();
if (inscrit == null)
Toast.makeText(MainActivity.this, "not exist", Toast.LENGTH_SHORT).show();
else
Toast.makeText(MainActivity.this, "exist", Toast.LENGTH_SHORT).show();
}
});
}
public void setInscrit(Inscrit inscrit) {
this.inscrit = inscrit;
}}
So the code should work like this:
the MainActivity should give the "inscrit" variable to the ConnexionAsyncTask
the ConnexionAsyncTask should verify if the email exist in the datastore or not and then put the result (Inscrit instance or null) in the "inscrit" variable with a setter
the MainActivity should verify if "inscrit" is null or not and show a toast
When i run my code i have to click 2 times to get the real result for example if i put "user#gmail.com" and this email exist of course in the datastore it will show me "not exist" for the first time and exist for second that's mean that the AsyncTask return the value just after the verification.
If i return value with .execute().get() it works but it blocks the ui thread and i want to show a progress Dialog.
I've tried to use a callback interface but it doesn't work either.
You should do the checking
if (inscrit == null)
Toast.makeText(MainActivity.this, "not exist", Toast.LENGTH_SHORT).show();
else
Toast.makeText(MainActivity.this, "exist", Toast.LENGTH_SHORT).show();
after your AsyncTask has finished executing. Basically, you are safe to check on inscrit nullability onPostExecute.
This question already has answers here:
How to save custom ArrayList on Android screen rotate?
(4 answers)
Closed 6 years ago.
I have an ArrayList with custom json objects fetched from the web with Volley. I would like to be able to save and restore these objects on a screen rotate. I would also like to save and restore my current scrolled position on screen rotate.
I have a sketchy idea that this can be done with onSaveInstanceState and onRestoreInstanceState?
Activity Code
public class MainActivity extends AppCompatActivity {
private final String TAG = "MainActivity";
//Creating a list of posts
private List<PostItems> mPostItemsList;
//Creating Views
private RecyclerView recyclerView;
private RecyclerView.Adapter adapter;
private RecyclerView.LayoutManager layoutManager;
private ProgressDialog mProgressDialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(TAG, "Device rotated and onCreate called");
//Initializing Views
recyclerView = (RecyclerView) findViewById(R.id.post_recycler);
layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
//Initializing the postlist
mPostItemsList = new ArrayList<>();
adapter = new PostAdapter(mPostItemsList, this);
recyclerView.setAdapter(adapter);
if (NetworkCheck.isAvailableAndConnected(this)) {
//Caling method to get data
getData();
} else {
final Context mContext;
mContext = this;
final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
alertDialogBuilder.setTitle(R.string.alert_titl);
alertDialogBuilder.setMessage(R.string.alert_mess);
alertDialogBuilder.setPositiveButton(R.string.alert_posi, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if (!NetworkCheck.isAvailableAndConnected(mContext)) {
alertDialogBuilder.show();
} else {
getData();
}
}
});
alertDialogBuilder.setNegativeButton(R.string.alert_nega, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
alertDialogBuilder.show();
}
}
//This method will get data from the web api
private void getData(){
Log.d(TAG, "getData called");
//Showing progress dialog
mProgressDialog = new ProgressDialog(MainActivity.this);
mProgressDialog.setCancelable(false);
mProgressDialog.setMessage(this.getResources().getString(R.string.load_post));
mProgressDialog.show();
//Creating a json request
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(ConfigPost.GET_URL,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.d(TAG, "onResponse called");
//Dismissing the progress dialog
if (mProgressDialog != null) {
mProgressDialog.hide();
}
/*progressDialog.dismiss();*/
//calling method to parse json array
parseData(response);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
//Creating request queue
RequestQueue requestQueue = Volley.newRequestQueue(this);
//Adding request to the queue
requestQueue.add(jsonArrayRequest);
}
//This method will parse json data
private void parseData(JSONArray array){
Log.d(TAG, "Parsing array");
for(int i = 0; i<array.length(); i++) {
PostItems postItem = new PostItems();
JSONObject jsonObject = null;
try {
jsonObject = array.getJSONObject(i);
postItem.setPost_title(jsonObject.getString(ConfigPost.TAG_POST_TITLE));
postItem.setPost_body(jsonObject.getString(ConfigPost.TAG_POST_BODY));
} catch (JSONException w) {
w.printStackTrace();
}
mPostItemsList.add(postItem);
}
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy called");
if (mProgressDialog != null){
mProgressDialog.dismiss();
Log.d(TAG, "mProgress dialog dismissed");
}
}
Thanks in advance.
Note a duplicate of How to save custom ArrayList on Android screen rotate?. While the arraylist in that question is declared in the Activity, mine is fetched with volley from the web. I don't know how to implement it for my arraylist, else this question wouldn't be asked
This is, in fact, a duplicate of the post you mentioned. Yes, the list was declared in the activity's onCreate() in that post, whereas you are doing it asynchronously. However, the idea is the same.
Once you have data to send, at any point of your application, it can be saved and restored.
The key, in your case, is to not call getData() every time the device is rotated. If you already have data loaded in mPostItemsList, then save and restore it via onSaveInstanceState(), and in onCreate() you get the data from the saved state. If that data does not exist, then you call getData().
public class MainActivity extends AppCompatActivity {
private final String TAG = "MainActivity";
private final String KEY_POST_ITEMS = "#postitems";
//Creating a list of posts
private List<PostItems> mPostItemsList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initializeViews();
if (savedInstanceState != null && savedInstanceState.containsKey(KEY_POST_ITEMS)){
mPostItemsList = savedInstanceState.getParcelableArrayList(KEY_POST_ITEMS);
} else {
//Initializing the postlist
mPostItemsList = new ArrayList<>();
if (NetworkCheck.isAvailableAndConnected(this)) {
//Caling method to get data
getData();
} else {
showNoNetworkDialog();
}
}
mAdapter = new PostAdapter(mPostItemsList, this);
recyclerView.setAdapter(adapter);
}
private void parseData(JSONArray array){
mPostItemsList.clear();
for(int i = 0; i<array.length(); i++) {
PostItems postItem = new PostItems();
JSONObject jsonObject = null;
try {
jsonObject = array.getJSONObject(i);
postItem.setPost_title(jsonObject.getString(ConfigPost.TAG_POST_TITLE));
postItem.setPost_body(jsonObject.getString(ConfigPost.TAG_POST_BODY));
} catch (JSONException w) {
w.printStackTrace();
}
mPostItemsList.add(postItem);
}
mAdapter.notifyDataSetchanged();
}
Edit: I didn't see the requirement to save scroll position. Look at Emin Ayar's answer for that. Also, a similar answer for it is also here: How to save recyclerview scroll position.
You can use onConfigurationChanged at your activity to detect rotation changes. Also you should track lastVisibleItemPosition with layoutManager.findLastVisibleItemPosition() and when rotation changed you should scroll to this position. You will need to use recyclerView.setOnScrollListener() to listen scrolls to keep your lastVisibleItemPosition updated
public class MainActivity extends AppCompatActivity {
private final String TAG = "MainActivity";
//Creating and initializing list of posts
private List<PostItems> mPostItemsList = new ArrayList<>();;
//Creating Views
private RecyclerView recyclerView;
private RecyclerView.Adapter adapter;
private RecyclerView.LayoutManager layoutManager;
private ProgressDialog mProgressDialog;
private int lastVisibleItemPos = -1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(TAG, "Device rotated and onCreate called");
if (NetworkCheck.isAvailableAndConnected(this)) {
//Caling method to get data and check if postList have value set before or not
// because this part will be called on every rotation change, we are controlling this
if (mPostItemsList.size() <= 0) {
//Initializing Views
recyclerView = (RecyclerView) findViewById(R.id.post_recycler);
layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
adapter = new PostAdapter(mPostItemsList, this);
recyclerView.setAdapter(adapter);
getData();
}
} else {
final Context mContext;
mContext = this;
final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
alertDialogBuilder.setTitle(R.string.alert_titl);
alertDialogBuilder.setMessage(R.string.alert_mess);
alertDialogBuilder.setPositiveButton(R.string.alert_posi, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if (!NetworkCheck.isAvailableAndConnected(mContext)) {
alertDialogBuilder.show();
} else {
getData();
}
}
});
alertDialogBuilder.setNegativeButton(R.string.alert_nega, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
alertDialogBuilder.show();
}
}
//This method will get data from the web api
private void getData(){
Log.d(TAG, "getData called");
//Showing progress dialog
mProgressDialog = new ProgressDialog(MainActivity.this);
mProgressDialog.setCancelable(false);
mProgressDialog.setMessage(this.getResources().getString(R.string.load_post));
mProgressDialog.show();
//Creating a json request
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(ConfigPost.GET_URL,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.d(TAG, "onResponse called");
//Dismissing the progress dialog
if (mProgressDialog != null) {
mProgressDialog.hide();
}
/*progressDialog.dismiss();*/
//calling method to parse json array
parseData(response);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
//Creating request queue
RequestQueue requestQueue = Volley.newRequestQueue(this);
//Adding request to the queue
requestQueue.add(jsonArrayRequest);
}
//This method will parse json data
private void parseData(JSONArray array){
Log.d(TAG, "Parsing array");
for(int i = 0; i<array.length(); i++) {
PostItems postItem = new PostItems();
JSONObject jsonObject = null;
try {
jsonObject = array.getJSONObject(i);
postItem.setPost_title(jsonObject.getString(ConfigPost.TAG_POST_TITLE));
postItem.setPost_body(jsonObject.getString(ConfigPost.TAG_POST_BODY));
} catch (JSONException w) {
w.printStackTrace();
}
mPostItemsList.add(postItem);
}
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// set your adapter here with your data
adapter = new PostAdapter(mPostItemsList, this);
recyclerView.setAdapter(adapter);
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy called");
if (mProgressDialog != null){
mProgressDialog.dismiss();
Log.d(TAG, "mProgress dialog dismissed");
}
}