I'm doing a lost property office application. It consists of four tabs, each tab must display announcement feed uploaded by users. By clicking on a particular item opens a new activity to derive more information.(Well, sort of news feed). I take the data from the API site in the form of JSON.
I did four tabs using ViewPager, Fragment. image my fragments
I have tried to place every Fragment listview and display their data with JSON with AsynTask. And caused AsyncTask for each fragment also called the same JSON in the first fragment. May be it is not right.
So, please tell me the correct move.
What used to for display data into listview from json
How to display information on a new activity that opens when you press the listview item?
Send to fragment over the intent or download a JSON again?
How to realize adding ads by user?
If possible, write the steps. Thank you very much, I will be glad of any help.
P.S Sorry for bad English
First of all you can use a simple list adapter to be able to put JSON data into a listview, you can see a tutorial of this here.
Second to be able to see details about a item in a list view you can use a onListItemClick, with extending ListActivity. An example of doing this would be:
MyListActivity.java
public class MyListActivity extends ListActivity {
// . . .
protected void onListItemClick(ListView l, View v, int position, long id) {
//handle the list click here
intent = new Intent(this, ListDetails.class);
//convert the position int into a string to pass to the intent
value = String.valueOf(position);
//put the value into the intent
intent.putExtra("key", value);
//start the activity here
MyListActivity.this.startActivity(intent);
}
}
ListDetails.java
public class ListDetails extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//gets the value sent with the intent
Intent intent = getIntent();
final String helpView = intent.getStringExtra("key");
// . . .
}
This is assuming that you are using a ListActivity to make the list and it really depends on what sort of information you want to display, if you want to display all the data, you could pass the JSON data as a string through the intent, then get it like in the example above.
Thirdly if you want to keep the JSON data you can just pass it along with the intent and then when the user presses back, just pass it back to the original activity once again through the intent. If you want to re-download the JSON data, you can, but to save with users mobile internet connection going over (especially for large JSON files repeatedly), in would not recommend using this option. If you want to download the JSON data again, you will need to use a AsyncTask to download the data, so not to disrupt the user interface and that it will raise a error when you try to do this (believe me, I have pulled my hair out over this). A example of a AsyncTask is (from the android project I am working on, that uses google maps to calculate a route):
private class ReadTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... url) {
String data = "";
try {
HttpConnection http = new HttpConnection();
data = http.readUrl(url[0]);
} catch (Exception e) {
Log.d("Background Task", e.toString());
}
return data;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
Log.i("Log","Parser Task Started");
Log.i("Log",result);
new ParserTask().execute(result);
}
}
private class ParserTask extends
AsyncTask<String, Integer, List<List<HashMap<String, String>>>> {
#Override
protected List<List<HashMap<String, String>>> doInBackground(
String... jsonData) {
JSONObject jObject;
List<List<HashMap<String, String>>> routes = null;
try {
jObject = new JSONObject(jsonData[0]);
PathJSONParser parser = new PathJSONParser();
routes = parser.parse(jObject);
} catch (Exception e) {
e.printStackTrace();
}
return routes;
}
#Override
protected void onPostExecute(List<List<HashMap<String, String>>> routes) {
//process the JSON data here
}
}
You would place this inside a activity, adding in the necessary processing for the JSON data inside the onPostExecute in ParserTask. To download the JSON data, you would call (replacing the url with your url for getting the JSON data):
String url = "http://www.example.com"
ReadTask downloadTask = new ReadTask();
downloadTask.execute(url);
EDIT:
Lastly to show the latest or most important/relevant lost property adverts, you can once again use JSON to get this from your backend website. In PHP you can customise server responses, sending back JSON responses depending on values in the GET (?thisIsTheGet=blahblahblah). To add advertisements you can create a seperate activity, with EditTexts etc, to create a form, then send the data through a GET request to your backend server (where the JSON is held), so the server can update the advertisement list. Once again you can use a AsyncTask to send the GET request to the server, perhaps using methods above to send back from the server the success of the adding of the advertisement. A example of what your form could look like (XML) would be:
activity_add_advertisement.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context="your.activity.class.root.activityAddAdvertisement"
tools:showIn="#layout/activity_add_advertisement"
android:id="#+id/LLMainContent"
android:orientation="vertical"
>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/edittext1"/>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/edittext2"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/submitButton"/>
</LinearLayout>
Then set a on click listener for the button being pressed inside the activity:
activityAddAdvertisement.java
public class activityAddAdvertisement {
// . . .
Button submitButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
// . . .
submitButton = (Button) findViewById(R.id.submitButton);
submitButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//call the methods from above to send a request to a url, with the contents of the edit texts in the GET request
}
}
}
You can add more EditTexts and other elements and inside the contents inside the GET request. The server will then edit the JSON to include the new advertisements. The PHP won't be too hard, if you need some tutorials on PHP, W3Schools has good tutorials and examples for you to use.
Further Reading:
Android Intents
Related
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 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.
I'm trying to populate a ListView with various objects obtained from a RESTApi.
To test if the connection, and the objects are actually recieved, I invoke this method:
protected void onPostExecute(String result) {
try {
JSONArray users = new JSONArray(result);
JSONObject user = users.getJSONObject(1);
Toast.makeText(MainActivity.this, user.getString("name"), Toast.LENGTH_LONG).show();
jsonList = users;
} catch (JSONException e) {
e.printStackTrace();
}
}
The Toast does show me the name of the current object, but whenever I try to populate my ListView, I get a NullPointerException.
I made a TextView to test if the JSON is actually there aswell, but here I get another NullPointerException:
textView.setText(user.getString("name"));
Why does it give me a NullPointer here, when the JSONObject works fine in the Toast?
As far as your code seems
You are accessing the first element of users object
You have to specify list view's first index as well,
you are accessing 1st element and passing to the whole listview
Please follow the basic programming of Listview
http://www.wingnity.com/blog/android-json-parsing-and-image-loading-tutorial/
Create a Bean class with getters and setters then populate the Bean with JSON data and use it as the data source to your listView adapter!
I am currently having trouble getting a value from an AsyncTask that gets data from a JSON connection. I have looked at a few examples, but mostly I have only seen posting results from AsyncTask.
First I have an object called Dog that only has a String, Name. I am trying to get the Name of the dog from the server.
Using the following code in my oncreate, I start the DogAsyncTask while assing in an URL called n and a Dog d_in.
Dog d_in = new Dog("DogName");
DogAsyncTask task = new DogAsyncTask(d_in);
String n = "www.dog.com";
task.execute(n);
Log.e("Out", d_in.getName());
My AsyncTask is as follows:
private class DogAsyncTask extends AsyncTask<String, Void, String> {
Dog d = null;
DogAsyncTask(Dog d){
this.d = d;
}
ProgressDialog mProgressDialog;
#Override
protected void onPostExecute(String result) {
d.setName(result);
Log.e("Dog", d.getName());
mProgressDialog.dismiss();
}
#Override
protected void onPreExecute() {
mProgressDialog = ProgressDialog.show(AsyncTestActivity.this, "Loading...", "Data is Loading...");
}
#Override
protected String doInBackground(String... name) {
//Go to url = name and then gets String below.
String outfromjson = "new dog name"; //This will be a function that gets a name from JSON
return outfromjson;
}
}
I tried using something like
Log.e("Out", task.d.getName());
but I keep getting the default name of the dog which is "DogName". How to I carry values out of AsyncTask?
OK, The thing what is happening here is:
You want to pass Dog as reference (pointers as in C / C++ / Objective-C),
and you want to reflect change in original variable using other variable.
but keep in mind that Java doesn't pass object by reference, Java passes objects by value (only value is transferred, another object is created and assigned value).
So what you can do is you can assign that result-holder object again as a value to the original object.
You can do the following,
Declare and implement an interface in your activity and then use it's methods as a callback from the onPostExecute method.
I'm parsing a large XML document and showing its contents in a ListView. Initially I was parsing the entire thing and then showing it all at once, but this takes pretty long to load (~30 seconds on some devices).
Now, as soon as my SAX handler gets an object I add it to an array and notify my list adapter that the data changed. This brings up a new problem because I'm rapidly refreshing the ListView the user is unable to scroll or select an item.
Is there a more efficient way to handle this?
Thanks.
Two things come to mind.
Make sure you are loading the data in a background thread
Don't overwhelm the UI loading one object at a time. Do them in batches of 10 or whatever number makes sense for you app.
I recommend you to use a progressdialog in a class that extends AsyncTask.
class MyAsyncLoad extends AsyncTask{
ProgressDialog myprogsdial;
#Override
protected void onPreExecute(){
myprogsdial = ProgressDialog.show(MyActivity.this, null, "Loading...", true);
}
#Override
protected Void doInBackground(Void... params) {
//here you are doing parsing stuff and load data into your datastructure, or whatever you use to store data from XML
return null;
}
#Override
protected void onPostExecute(Void result){
myprogsdial.dismiss();
//here you update the cursor,something like
adapter = new CursorAdapter(context, cursor...)
setListAdapter(adapter);
adapter.notifyDataSetChanged();
}
}