I am using this Volley example
It works perfect, but when I change the response of data to 150+ records from server it takes a long time to load.
So I want to load small amount of data 5-10 record then another 5-10 records.
How can I do this with Volley?
Volley will fetch all the response which it is supposed to receive at client end(Mobile end). This type of behavior cannot be accomplished on Client Side or Mobile end.
This should be done in the API or server side by implementing pagination in services, something like below:
http://serviceendpoint.com?start=0&&end=5 fetch first five record.
http://serviceendpoint.com?start=5&&end=10 fetch next five record.
//Constant Variable denoting after how many
//to call in one service
//items numbers you need
private final int LIST_FETCH_COUNT =5;
private final int TOTAL_COUNT=1500;
private int start=0;
private int end=0;
//you can do something like this
for(int i=0;i<TOTAL_COUNT;i+=LIST_FETCH_COUNT){
callAsyncService(i,i+LIST_FETCH_COUNT);
}
private void callAsyncService(int start,int end){
//create a new async object
asynObject.execute(Void,Void,start,end);
}
//inside your async
doInBackground(params...){
//get start and end values from params and run a service
}
You could use AsyncTask to do something like this:
private class DatabaseTask extends AsyncTask<URL, Integer, String> {
protected String doInBackground(URL... urls) {
//put here your volley query.
}
return results;
}
protected void onProgressUpdate(Integer... progress) {
//You can show the progress of the download with this function:
setProgressPercent(progress[0]);
}
protected void onPostExecute(String results) {
//Parse the results here and show them in the UI.
}
}
Then, assuming you are trying to connect to an online database, for example a MySQL database, you could easily implement a PHP interface to your database which returns only the amount of records you want (for example 10) and call the DatabaseTask whenever you need the records.
Alternatively, you could do a separate Thread working on a timer which sends query whenever the timer fires.
Related
I already searched how refresh data in recycler view using retrofit library to get data but unfortunately I can't find anything.
Could you please put me on right direction where I can find information.
I got App when customer make order and see order status, how to make when person update order status, example from 0 in 1 in database, so that's mean it's changed value but retrofit only loaded data when status is 0. How to make when App recognice a value is updated in database and show to customer not 0 status but 1.
Thank you so much
private Handler mRepeatHandler;
private Runnable mRepeatRunnable;
private final static int UPDATE_INTERVAL = 2000;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mRepeatHandler = new Handler();
mRepeatRunnable = new Runnable() {
#Override
public void run() {
//Put the piece of code which is getting data from server.
mRepeatHandler.postDelayed(mRepeatRunnable, UPDATE_INTERVAL);
};
mRepeatHandler.postDelayed(mRepeatRunnable, UPDATE_INTERVAL);
}
You can use DiffUtil, an Android support library utility class, which helps to ease out the process of finding which item changed in a list of data. It helps to calculate the difference between an old list and a new list and trigger updates to list items.
Here is the example link
I am currently building an android app, that uses a small database which consists of two entity-data-classes (Card and CardDeck) and a third one representing a many to many relationsship between the former two by mapping there long id primary keys together (CardInCardDeckRelation).
Now I want to insert a new Deck into my database, which works just fine, but if I want to insert some CardInCardDeckRelation-objects afterwards by using the id returned from the insertCardDeck()-method it fails because the insertion calls on the relationship-table occur before the insertion of the cardDeck object is finished so I am always getting the wrong cardDeck-id.
I think I am going into the right direction by using a Async-task to insert my CardDeck however I don't know to proceed from there since I can only pass one set of Arguments to my async-task object, so I can't pass my Relationshipobjects to be inserted in say for example a onPostExecute-method in the Async-task-class.
This my insert-method in my Repository-class:
public void insertCardDeckAsync(CardDeck cardDeck){
new insertAsyncTaskDao(mCardDeckDao).execute(cardDeck);
}
private static class insertAsyncTaskDao extends AsyncTask<CardDeck, Void, Void> {
private CardDeckDao mAsyncTaskDao;
insertAsyncTaskDao(CardDeckDao dao){
mAsyncTaskDao = dao;
}
#Override
protected Void doInBackground(final CardDeck... params){
mAsyncTaskDao.insertCardDeck(params[0]);
return null;
}
#Override
protected void onPostExecute(Void v){
//maybe insert Relationship object here?
}
}
I would be very thankful if someone could provide a way to properly insert an entity object and some many-to-many relationsship objects afterwards, using the id generated by the former insert.
So after some testing i figured out my error:I was initially using an Executor which I defined somewhere else in my App to handle database operations, so I don't have to create a private inner class extending AsyncTask for every database operation in my Repository class.For some reason though my usage of Executor does seem to block the particular thread when executing database-queries so:
mExecutors.diskIO().execute(new Runnable(){
//insert new Deck
//insert Many-to-Many relationsship-object
}
would execute both operations immediately after one another, thus causing a SQL-ForeignConstraint-related error, because it tries to insert the realtion objects before the actual deck object is inserted.
The solution to this is to just use a AsyncTask instead, handling all the database operation in the right order in the doInBackground-method:
#Override
protected Void doInBackground(final CardDeck... params){
// insert new deck object into database
insertionId = mAsyncTaskDao.insertCardDeck(params[0]);
// create relations-array
CardInCardDeckRelation[] relations = new CardInCardDeckRelation[STANDARD_CARDS.length];
// insert standard-card objects into array
for(int i = 0; i < STANDARD_CARDS.length; i++){
relations[i] = new CardInCardDeckRelation(insertionId,
mAsyncCardDao.getStandardCardByName(STANDARD_CARDS[i]),
i);
}
// insert created array into database
mRelationDao.insertMultiple(relations);
Log.d(LOG_TAG, "Deck inserted");
return null;
}
If anyone needs further explanation I can provide the whole AsyncTask class.
I am fetching data from web service and storing it to SQLite database. The records I'm fetching are more in number so it takes too much time to fetch the data. I want to fetch this data such that while fetching data I can use the app. That is I want to fetch data in the background like we download large files. While downloading we can do the rest of task. How should I implement it in my app?
you should call web service from asyncktask which works on background.
#Override
protected String doInBackground(String... params) {
//call your webservice from here;
return ;
}
In the beginning I was using my custom Asynctask, but fetch information from a web service was very slow. Now I use Retrofit, and the time is very short. My best advice is that implements Retrofit.
Retrofit
already there are lot of answers similar to this is available, anyway here is the sample code.
create a innerClass name as MyAsyncClass
class MyAsyncClass{
#Override
protected Object doInBackground(Void... params) {
// write your method to fetch data from network
}
#Override
protected void onPostExecute(Object output) {
// do what ever you want to do with 'output' data
}
}
now you can call this class like this
MyAsyncClass myAsyncClass = new MyAsyncClass();
myAsyncClass.execute();
and here you can open some new activity.
Intent intent = new Intent(this, yourActivityName.class);
startActivity(intent);
I don't understand how is the Parse working?
I download data in parse to my arraylist , but when I show the Pets.size inside (//here) method "done" it will show 4, but when I show pets.size outside the done's method it will show 0?
public class Test extends AppCompatActivity {
ArrayList<Pet> pets;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
pets = new ArrayList<>();
ParseQuery<Pet> query = new ParseQuery<>("Pets");
query.findInBackground(new FindCallback<Pet>() {
#Override
public void done(List<Pet> list, ParseException e) {
if (e!=null){
Toast.makeText(Test.this,"Error",Toast.LENGTH_LONG).show();
}
for (Pet pet : list){
Pet newPet = new Pet();
newPet.setName(pet.getName());
newPet.setType(pet.getType());
pets.add(newPet);
}
// here
}
});
Toast.makeText(Test.this,"You have "+pets.size()+" pets",Toast.LENGTH_LONG).show();
}
Here's my Pet class:
#ParseClassName("Pets")
public class Pet extends ParseObject {
public String getName(){
return getString("name");
}
public void setName(String name) {
put("name", name);
}
public String getType(){
return getString("type");
}
public void setType(String type) {
put("type", type);
}
}
And an orther question , what should I do if I wanna save the data in local data?
Explanation:
findInbackground performs an operation to find all ParseObjects in a background thread (outside the main thread, or UI thread). So when it completes in the place where you have the comment
//here
That is when the background thread finishes it's call to find the objects. When you try to look at the size of the array outside that call where it shows size of 0, it is because it reached that point before the background thread finishes it's work (of adding to your array from objects it found).
What is happening is the operation for find() is happening in parallel with your main threads code.
And for your second question, make sure you enableLocalDatastore and then you can pin results from queries to your local cache. This data is stored on the device until the user deletes your app or clears cached data in settings.
Follow this guide to setup local cache Local Datastore with Parse
Note: A solution to your problem for when the background task of finding the pets is complete is to call a method from within the Callback for the findInBackground call that will handle the newly found Pet ParseObjects. Also remember to handle if the query fails either by finding no objects or some failure in connection / timeout.
just calling pet.pin() or pet.pinInBackground(); you can save a parseObject in local storage , to query objects in local storage you need set query.fromPin(true)
https://parse.com/docs/android/guide#objects-the-local-datastore
"done" method fires when the background task ends.
I am creating an app in Android and I have a large number of string data, lets way 10,000 or more words (items), I want to display it in a list view. My question is where should I put my (source) data
String Array in Xml file
In DB (then i have to place an external DB)
Reading data from a simple text file, CSV etc
Here my only concern is speed, which way is faster and why.
Note: I am currently placing data in Xml as string array and getting it in Array in activity, but it is slow it takes few sec/moments to load data from xml but only for the first time.
Execute the code to parse/load content form json/db in a AsyncTask for more speed. I load 5000 rows with ~ 400 chars per row. It takes without AsyncTask much longer.
private class YourTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... s) {
//Here you have to make the loading / parsing tasks
//Don't call any UI actions here. For example a Toast.show() this will couse Exceptions
// UI stuff you have to make in onPostExecute method
}
#Override
protected void onPreExecute() {
// This method will called during doInBackground is in process
// Here you can for example show a ProgressDialog
}
#Override
protected void onPostExecute(Long result) {
// onPostExecute is called when doInBackground finished
// Here you can for example fill your Listview with the content loaded in doInBackground method
}
}
To execute you just have to call:
new YourTask().execute("");
Here you can learn more about AsyncTasks:
AsyncTask developer Guide