Android: Save JSON data into SharedPreferences - android

I have this ListView which fetches its data (image+text) from JSON on the web.
Now I have a task to make the ListView is accessible without internet connection. My idea is by saving the JSON data from the web when the app is run for the first time with internet, and when it can't find internet connection it will get the data from the persistent Storage.
Can anybody help me with this? I'm still a beginner can't find the example of SharedPreferences with JSON.
Thanks a lot
public class ProjectsList extends Activity {
/** Called when the activity is first created. */
//ListView that will hold our items references back to main.xml
ListView lstTest;
//Array Adapter that will hold our ArrayList and display the items on the ListView
ProjectAdapter arrayAdapter;
//List that will host our items and allow us to modify that array adapter
ArrayList<Project> prjcts=null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.projects_list);
//Initialize ListView
lstTest= (ListView)findViewById(R.id.lstText);
//Initialize our ArrayList
prjcts = new ArrayList<Project>();
//Initialize our array adapter notice how it references the listitems.xml layout
arrayAdapter = new ProjectAdapter(ProjectsList.this, R.layout.listitems,prjcts,ProjectsList.this);
//Set the above adapter as the adapter of choice for our list
//lstTest.setAdapter(arrayAdapter);
lstTest.setAdapter(arrayAdapter);
if (isOnline())
{
//Instantiate the Web Service Class with he URL of the web service not that you must pass
WebService webService = new WebService("http://liebenwald.spendino.net/admanager/dev/android/projects.json");
//Pass the parameters if needed , if not then pass dummy one as follows
Map<String, String> params = new HashMap<String, String>();
params.put("var", "");
//Get JSON response from server the "" are where the method name would normally go if needed example
// webService.webGet("getMoreAllerts", params);
String response = webService.webGet("", params);
try
{
//Parse Response into our object
Type collectionType = new TypeToken<ArrayList<Project>>(){}.getType();
//JSON expects an list so can't use our ArrayList from the lstart
List<Project> lst= new Gson().fromJson(response, collectionType);
//Now that we have that list lets add it to the ArrayList which will hold our items.
for(Project l : lst)
{
prjcts.add(l);
ConstantData.projectsList.add(l);
}
//Since we've modified the arrayList we now need to notify the adapter that
//its data has changed so that it updates the UI
arrayAdapter.notifyDataSetChanged();
}
catch(Exception e)
{
Log.d("Error: ", e.getMessage());
}
}
lstTest.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent care = new Intent(ProjectsList.this, ProjectDetail.class);
care.putExtra("spendino.de.ProjectDetail.position",position);
startActivity(care);
}
});
}
#Override
public void onDestroy()
{
yAdapter.imageLoader.stopThread();
lstTest.setAdapter(null);
super.onDestroy();
}
protected boolean isOnline() {
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
if (netInfo != null && netInfo.isConnected()) {
return true;
} else {
AlertDialog.Builder alertbox = new AlertDialog.Builder(this);
alertbox.setTitle("spendino Helfomat");
alertbox.setMessage ("Please check your internet connection");
alertbox.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
//Main.this.finish();
}
});
alertbox.show();
return false;
}
}
}

SharedPreferences has no methods for saving a JSON object as is, you must try to convert it to a String. Then when getting it you must parse this String back to JSON. Good luck!
JSON to String:
JSONObject o = new JSONObject(data.trim());
String name = o.getString(Constants.NAME);
long date = o.getLong(Constants.DATE);
String mes = o.getString(Constants.MESSAGE);
StringBuilder buf = new StringBuilder(text.getText());
buf.append(name).append(" (").append(dfTime.format(new Date(date))).append(")\n").append(mes).append("\n");
text.setText(buf.toString());
Making a JSON from a String is not a harder task, use StringTokenizer. Good luck!

Related

Loader, Json and reload the data coming from the server

I'm working on a simple and small app (as an exercise) that suppose to collect some data from a JSON file and display in an activity.
The same activity has a spinner that when the user select an element should "reload" the Loader by passing a parameter that will modify the query to the server and get different info from the JSON file.
public class ChooseMatchActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<List<Match>> {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_choose_match);
Intent intent = getIntent();
mCurrentPetUri = intent.getData();
ArrayList<String> days = new ArrayList<String>();
SimpleDateFormat sdf = new SimpleDateFormat("EEEE dd-MMM-yyyy");
for (int i = 0; i < 7; i++) {
Calendar calendar = new GregorianCalendar();
calendar.add(Calendar.DATE, i);
String day = sdf.format(calendar.getTime());
days.add(day);
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item, days);
final Spinner spinDays = (Spinner)findViewById(R.id.spinner_days);
spinDays.setAdapter(adapter);
spinDays.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> arg0, View arg1,
int arg2, long arg3) {
setMatchesOfTheDay(spinDays.getSelectedItem().toString().toLowerCase());
}
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
});
ListView matchListView = (ListView) findViewById(R.id.list);
mAdapter = new MatchAdapter(this, new ArrayList<Match>());
matchListView.setAdapter(mAdapter);
mEmptyStateTextView = (TextView) findViewById(R.id.empty_view);
matchListView.setEmptyView(mEmptyStateTextView);
mStateProgressBar = (ProgressBar) findViewById(R.id.loading_spinner);
ConnectivityManager connMgr = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
// Get details on the currently active default data network
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
// If there is a network connection, fetch data
if (networkInfo != null && networkInfo.isConnected()) {
// Get a reference to the LoaderManager, in order to interact with loaders.
LoaderManager loaderManager = getLoaderManager();
// Initialize the loader. Pass in the int ID constant defined above and pass in null for
// the bundle. Pass in this activity for the LoaderCallbacks parameter (which is valid
// because this activity implements the LoaderCallbacks interface).
loaderManager.initLoader(MATCH_LOADER_ID, null, this);
} else {
// Otherwise, display error
// First, hide loading indicator so error message will be visible
mStateProgressBar.setVisibility(View.GONE);
mEmptyStateTextView.setText(R.string.no_internet_connection);
}
}
The following are the 4 methods that I use to deal with the loader and to intercept the value selected on the spinner
public void setMatchesOfTheDay(String day) {
Toast.makeText(this, "You choose the day: " + day,
Toast.LENGTH_SHORT).show();
Uri baseUri = Uri.parse(USGS_REQUEST_URL);
Uri.Builder uriBuilder = baseUri.buildUpon();
uriBuilder.appendQueryParameter("format", "geojson");
uriBuilder.appendQueryParameter("limit", "30");
new MatchLoader(this, uriBuilder.toString());
}
#Override
public Loader<List<Match>> onCreateLoader(int i, Bundle bundle ) {
// Create a new loader for the given URL
Uri baseUri = Uri.parse(USGS_REQUEST_URL);
Uri.Builder uriBuilder = baseUri.buildUpon();
uriBuilder.appendQueryParameter("format", "geojson");
uriBuilder.appendQueryParameter("limit", "10");
return new MatchLoader(this, uriBuilder.toString());
}
#Override
public void onLoadFinished(Loader<List<Match>> loader, List<Match> matches) {
// Set empty state text to display "No earthquakes found."
mEmptyStateTextView.setText(R.string.no_matches);
mStateProgressBar.setVisibility(View.GONE);
// Clear the adapter of previous earthquake data
mAdapter.clear();
// If there is a valid list of {#link Match}s, then add them to the adapter's
// data set. This will trigger the ListView to update.
if (matches != null && !matches.isEmpty()) {
mAdapter.addAll(matches);
}
}
#Override
public void onLoaderReset(Loader<List<Match>> loader) {
// Loader reset, so we can clear out our existing data.
mAdapter.clear();
}
The first time I access the activity everything is working perfectly but as soon as I select an element from the spinner I can see the Toast message but nothing change in the listview.
I tried several option but I definitely feeling confuse about working with the Loader
Hope someone can clarify a bit the concepts
Your setMatchesOfTheDay method is calling new MatchLoader(this, uriBuilder.toString());, but that does nothing - it creates a new Loader, but doesn't actually start it loading. The only way to start something loading is via initLoader (which only creates a Loader for the given ID if it doesn't already exist) or restartLoader (which throws away any existing Loader for the given ID and creates a new Loader).
In your case, it looks like you should be calling restartLoader(MATCH_LOADER_ID, null, this) at the end of your setMatchesOfTheDay to recreate your Loader with the newly selected date.

How can I call an activity within the same activity?

I have an activity that creates a list based on a list of series values returned by an http request. If the list includes a list of places, I call the next activity and pass some values through intents. However, if the response does not include a list of places, I need to repopulate my activity with a new list of series values, but I'm not sure how to call the same activity within the activity I'm already in. My attempt is below.
EDIT: the goal of refreshing the activity is to make an https request with new parameters in the url. I tried just recalling the http request earlier, but had no luck
protected void onPostExecute(JSONObject result){
ArrayList<String> modelNames = new ArrayList<>();
Log.d("JSON RESPONSE", result.toString());
final ArrayList<JSONObject> modelsObjectList = new ArrayList<>();
try {
JSONObject info = result.getJSONObject("info");
JSONArray models = info.getJSONArray("models");
for(int i = 0; i < models.length(); i++){
modelsObjectList.add(models.getJSONObject(i));
}
for(int i = 0; i < modelsObjectList.size(); i++){
modelNames.add(modelsObjectList.get(i).getString("name"));
}
} catch(JSONException e ){
Log.d("JSONEXCEPTION", e.getMessage().toString());
}
//TODO found problem, model names for whatever reason is passing in the names from previous activity
Log.d("MODEL NAMES", modelNames.toString());
Toast.makeText(AfterDestinationActivity.this, modelNames.toString(), Toast.LENGTH_LONG).show();
mList = (ListView) findViewById(android.R.id.list);
CustomMainAdapter mainAdapter = new CustomMainAdapter(AfterDestinationActivity.this, modelNames);
mList.setAdapter(mainAdapter);
setProgressBarIndeterminateVisibility(false);
mList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
String name;
Long id;
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
JSONObject passingObject = modelsObjectList.get(position);
ArrayList<String> nextPlacesList = new ArrayList<>();
Log.d("AD OBJECT PRESSED ON", passingObject.toString());
//TODO found issues with debugging
try {
JSONArray places;
JSONArray series = passingObject.getJSONArray("series");
name = passingObject.getString("name");
id = passingObject.getLong("id");
Log.d("NEXT ACTIVITY NAME", name);
System.out.println("NEXT ACTIVITY ID " + id);
Log.d("NEXT SERIES LIST", nextPlacesList.toString());
//if there are no places, launch http request again for series
if(passingObject.optJSONArray("places") == null){
ArrayList<String> sameSeries = new ArrayList();
System.out.println("WENT INTO FOR LOOP");
for(int i = 0; i < series.length(); i++){
sameSeries.add(series.getString(i));
Log.d("AD FOR LOOP SERIES", series.getString(i));
}
Intent refreshActivity = new Intent(AfterDestinationActivity.this, AfterDestinationActivity.class);
refreshActivity.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
refreshActivity.putExtra("id", id);
refreshActivity.putExtra("name", name);
refreshActivity.putExtra("placesList", nextPlacesList);
Log.v("RESTARTING ACTIVIY", "activity restating");
startActivity(refreshActivity);
}
} catch(JSONException e){
Log.d("JSONEXCEPTION", "IN THERE " + e.getMessage());
}
Intent intent = new Intent(AfterDestinationActivity.this, PlacesListActivity.class);
intent.putExtra("id", id);
intent.putExtra("name", name);
intent.putExtra("placesList", nextPlacesList);
startActivity(intent);
}
});
}
Simply use this,
add this in your manifest,
<activity android:name=".StartActivity" android:label="#string/app_name"
android:clearTaskOnLaunch="true">
</activity>
From JAVA code use this,
Intent refreshActivity = new Intent(AfterDestinationActivity.this, AfterDestinationActivity.class);
refreshActivity.putExtra("id", id);
refreshActivity.putExtra("name", name);
refreshActivity.putExtra("placesList", nextPlacesList);
Log.v("RESTARTING ACTIVIY", "activity restarting");
startActivity(refreshActivity);
You don't need to call the same activity. Just update the corresponding views with the new values in your activity.
I would access it via the "this pointer" or an interface:
EDIT
MyActivity extends Activity implements IUpdateListener
{
public void onCreate(Bundle onSaveInstanceState)
{
//code
}
#Override
void onUpdate(Result result)
{
//update data or do other stuff - like start another activity or populate urs.
}
}
Next The AsynTask:
MyAsyncTask extends AsyncTask<Void, Void, Result>
{
private IUpdateListener listener;
public MyAsyncTask(IUpdateListener listener)
{
this.listener = listener;
}
Result doInBackground(Void.. voids)
{
//http request and parse - an object Result
return result data;
}
void onPostExecute(Result result)
{
if(result!=null) - or other operation u want
{
listener.OnUpdate(result) - or other stuff you want.
}
}
Next the interface:
interface IOnUpdateListener
{
onUpdate(Result result);
}
"this pointer":
How can I access my Activity's instance variables from within an AlertDialog's onClickListener?
I hope I was clear enough.

Android: Refresh ListView every minute

I've been reading all day threads regarding this issue I came up with a strategy but can't make it work
I have a listview fetching json data from a sql server
this listview already has a on swipe refresh function
I need this listview to refresh automatically only when new row was inserted in the data base.
So I wrote a php file fetching number of rows and echoing it witha 3 second refresh (on the php itself) so every time I enter the php file I get the realtime row numbers of my table.
I'm trying to build a function inside my MainActivity:
int OldNumberOfRows = data from the php file
while(true){
int newNumberOfRows = fetch data again using that php
if(both arent equal) execute refresh command.
}
Note: I got no idea how to extract the string from my asynctask to start manipulating my code with it.
That's it in general, Iv'e added the main activity , the "outer class" (FetchNumRowAsync) calling that php the swipe class and the php itself
MainActivity:
public class MainActivity extends AppCompatActivity implements SwipeRefreshLayout.OnRefreshListener {
private String TAG = MainActivity.class.getSimpleName();
private String URL = "http://troyka.esy.es/troyka/orders.php";
private SwipeRefreshLayout swipeRefreshLayout;
private ListView listView;
private SwipeListAdapter adapter;
private List<Order> orderList;
// initially offset will be 0, later will be updated while parsing the json
private int offSet = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new FetchRowNumAsync(this).execute("http://troyka.esy.es/numberofrows.php");
listView = (ListView) findViewById(R.id.listView);
//RelativeLayout.LayoutParams layout_description = new RelativeLayout.LayoutParams(50,10);
//Rl.setLayoutParams(layout_description);
swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh_layout);
orderList = new ArrayList<>();
adapter = new SwipeListAdapter(this, orderList);
listView.setAdapter(adapter);
swipeRefreshLayout.setOnRefreshListener(this);
/**
* Showing Swipe Refresh animation on activity create
* As animation won't start on onCreate, post runnable is used
*/
swipeRefreshLayout.post(new Runnable() {
#Override
public void run() {
swipeRefreshLayout.setRefreshing(true);
fetchOrders();
}
}
);
}
/**
* This method is called when swipe refresh is pulled down
*/
#Override
public void onRefresh() {
fetchOrders();
}
/**
* Fetching movies json by making http call
*/
private void fetchOrders() {
// showing refresh animation before making http call
swipeRefreshLayout.setRefreshing(true);
// appending offset to url
String url = URL + offSet;
// Volley's json array request object
JsonArrayRequest req = new JsonArrayRequest(url,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.d(TAG, response.toString());
if (response.length() > 0) {
// looping through json and adding to order list
for (int i = 0; i < response.length(); i++) {
try {
JSONObject orderObj = response.getJSONObject(i);
int rank = orderObj.getInt("rank");
String title = orderObj.getString("title");
Order m = new Order(rank, title);
orderList.add(0, m);
// updating offset value to highest value
if (rank >= offSet)
offSet = rank;
} catch (JSONException e) {
Log.e(TAG, "JSON Parsing error: " + e.getMessage());
}
}
adapter.notifyDataSetChanged();
}
// stopping swipe refresh
swipeRefreshLayout.setRefreshing(false);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "Server Error: " + error.getMessage());
Toast.makeText(getApplicationContext(), error.getMessage(), Toast.LENGTH_LONG).show();
// stopping swipe refresh
swipeRefreshLayout.setRefreshing(false);
}
});
// Adding request to request queue
MyApplication.getInstance().addToRequestQueue(req);
}
}
FetchRowNumAsync:
public class FetchRowNumAsync extends AsyncTask<String, Void, String> {
private Context mContext;
public FetchRowNumAsync(Context ctx){
this.mContext = ctx;
}
protected String doInBackground(String... urls)
{
String fullString = "";
try{
URL url = new URL(urls[0]);
BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));
String line;
while ((line = reader.readLine()) != null) {
fullString += line;
}
reader.close();
}catch(Exception e ){
e.getMessage();
}
return fullString;
}
#Override
protected void onPostExecute(String value){
try{
((OnValueFetchedListener) mContext).onValueFetched(value);
}catch(ClassCastException e){}
}
public interface OnValueFetchedListener{
void onValueFetched(String columns);
}
}
SwipeListAdapter:
public class SwipeListAdapter extends BaseAdapter {
private Activity activity;
private LayoutInflater inflater;
private List<Order> orderList;
private String[] bgColors;
public SwipeListAdapter(Activity activity, List<Order> orderList) {
this.activity = activity;
this.orderList = orderList;
bgColors = activity.getApplicationContext().getResources().getStringArray(R.array.movie_serial_bg);
}
#Override
public int getCount() {
return orderList.size();
}
#Override
public Object getItem(int location) {
return orderList.get(location);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (inflater == null)
inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null)
convertView = inflater.inflate(R.layout.list_row, null);
TextView serial = (TextView) convertView.findViewById(R.id.serial);
TextView title = (TextView) convertView.findViewById(R.id.title);
serial.setText(String.valueOf(orderList.get(position).id));
title.setText(orderList.get(position).title);
String color = bgColors[position % bgColors.length];
serial.setBackgroundColor(Color.parseColor(color));
return convertView;
}
}
PHP
<?php
header("refresh: 3;");
$mysqli = new mysqli("irrelevant","irrelevant","irrelevant","irrelevant");
/* check connection */
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
$query = "SELECT COUNT(*) FROM orders";
$result = mysqli_query($mysqli,$query);
$rows = mysqli_fetch_row($result);
echo ($rows[0]);
$result->close();
$mysqli->close();
?>
Try this approach:
Create an endpoint in your server like the following:
//http://somesite.com/api/data/pull/check
Then, you can easily check this endpoint that returns some value like true or false depending on whether there is new data inserted into the db.
From the result you receive, you can then decide on whether to refresh your data on the phone by making another HTTP request or not. You always want to avoid making unnecessary requests to the server - remember users spend money every time they use their data plan (service).
I, like in the comments above, recommend having a column with a timestamp that you can check so that you only get the newly added data instead of everything!
I hope this gives you a simple idea on how to approach this issue! Good luck!
android app will not know when you have added/updated data in your table on the server until and unless you call script from app and fetch the data and update in your device.
only if your app has implemented these feature's
push notification- call Script every time you receive notification.
XMPP service- used for chat apps(which is not probably answer for
your question right now)
here is my suggestion for you
From server side:
create timestamp field in your table on server. update it with
current timestamp value every time you do changes(i.e update/add) in
the table.and when when that script is called send it across in json
and make your app save it in sqlite along with data.
server will compare for timestamp posted by app everytime with the
saved timestamp in the server for new data.
from client side:
for fist time timestamp from app will be 0. server will check it and
send the whole data along with the timestamp saved during changes in
table. save the data along with time stamp . second time when the
script is called App will be sending the timestamp that was last
saved.
with all this your app will not come to know still if new data is added until you call script and check. but atleast it will come to know if new data is received or not and whether to refresh ur screen
now comes script calling part from client side that is executing of assynch task, do it using handler to execute assynch class every minute
final Handler timerHandler = new Handler();
Runnable timerRunnable;
timerRunnable = new Runnable() {
#Override
public void run() {
new FetchRowNumAsync(context).execute(url);
timerHandler.postDelayed(timerRunnable, 60000); // run every minute
}
};
and unregister it in onDestroy()
#Override
public void onDestroyView() {
// TODO Auto-generated method stub
super.onDestroyView();
timerHandler.removeCallbacks(timerRunnable);
}

Managing the background thread within Android application

I currently have this class below which parses json urls and loads images and texts into a listview with the help of the Lazy Adapter Class and background thread.
Each list item consists of an image view and 2 text views.
I want to create pop up boxes (alert dialog) for each of the generated list items. The alert dialog will have options which will call other applications.
My question :
Would it be wise to code this alert dialog functionality in this class? I'm worried that there is a lot of stuff currently being done in the background and it might affect the app's functionality.
If not could anyone suggest another way to do it. thanks.
Json Activity Class :
public class JsonActivity extends SherlockActivity{
private ProgressDialog progressDialog;
// JSON Node names
static final String TAG_NAME = "name";
static final String TAG_IMAGEURL = "imageurl";
ListView list;
LazyAdapter adapter;
String chartUrl;
String[] urlNames = new String[] {
"urls..."
};
// chartItemList is the array list that holds the chart items
ArrayList<HashMap<String, String>> chartItemList = new ArrayList<HashMap<String,
String>>();
//Holds imageurls
ArrayList<String> imageurls = new ArrayList<String>();
JsonParser Parser = new JsonParser();
// JSONArray
JSONArray chartItems = null;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.chart);
//Get the bundle
Bundle bundle = getIntent().getExtras();
//Extract the data from the bundle
int chartIndex = bundle.getInt("chartIndex");
String chartUrl = urlNames[chartIndex];
setTitle(bundle.getString("chartname"));
//url from where the JSON has to be retrieved
String url = chartUrl;
//Check if the user has a connection
ConnectivityManager cm = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = cm.getActiveNetworkInfo();
if (info != null) {
if (!info.isConnected()) {
Toast.makeText(this, "Please check your connection and try again.",
Toast.LENGTH_SHORT).show();
}
//if positive, fetch the articles in background
else new getChartItems().execute(chartUrl);
}
//else show toast
else {
Toast.makeText(this, "Please check your connection and try again.",
Toast.LENGTH_SHORT).show();
}
}
class getChartItems extends AsyncTask<String, String, String> {
// Shows a progress dialog while setting up the background task
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = new ProgressDialog(JsonActivity.this);
progressDialog.setMessage("Loading chart...");
progressDialog.setIndeterminate(false);
progressDialog.setCancelable(false);
progressDialog.show();
}
//Gets the json data for chart items data and presents it in a list view
#Override
protected String doInBackground(String... args) {
String json = Parser.getJSONFromUrl(args[0]);
String imageurl;
String rank;
String name;
String url;
try{
chartItems = new JSONArray(json);
JSONObject json_data=null;
for(int i=0;i<chartItems.length();i++){
json_data = chartItems.getJSONObject(i);
//Retrieves the value of the name from the json object
name=json_data.getString("name");
//Retrieves the image url for that object and adds it to an arraylist
imageurl=json_data.getString("imageurl");
//imageurls.add(imageurl);
HashMap<String, String> hashMap = new HashMap<String, String>();
// adding each child node to HashMap key => value
//hashMap.put(TAG_RANK, rank);
hashMap.put(TAG_NAME, name);
hashMap.put(TAG_IMAGEURL, imageurl);
// adding HashMap to ArrayList
chartItemList.add(hashMap);
}
;
}
catch (JSONException e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
public void run() {
list=(ListView)findViewById(R.id.list);
// Getting adapter by passing xml data ArrayList
adapter = new LazyAdapter(JsonActivity.this, chartItemList);
list.setAdapter(adapter);
// Click event for single list row
list.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
}
});
}
});
return null;
}
//Removes the progress dialog when the data has been fetched
protected void onPostExecute(String args) {
progressDialog.dismiss();
}
}
}
My answer for this is Yes, it is wise enough to implement one more level network communication as far as your use case justifies it.
This depends on communication channel (EDGE/ 3G/ 4G/ WiFi) and use case of the application. Technically it is pretty much possible as far as you are doing this in background. It also depends on the size of the list which you are loading. Best way to check this is by implementing plug-able code and try it out.

Android: Make LazyLoading ListView from GSON available without internet

I've just implemented GSON to Fedor's LazyLoading ListView. That means the app saves the downloaded images and texts from the web to the external storage though an ImageLoader class.
and I wonder why how to make this listview accessible without an internet connection.
Here I give you a snippet of my ListView Class:
public class ProjectsList extends Activity {
ListView lstTest;
ProjectAdapter arrayAdapter;
ArrayList<Project> prjcts=null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.projects_list);
//Initialize ListView
lstTest= (ListView)findViewById(R.id.lstText);
prjcts = new ArrayList<Project>();
arrayAdapter = new ProjectAdapter(ProjectsList.this, R.layout.listitems,prjcts,ProjectsList.this);
lstTest.setAdapter(arrayAdapter);
if (isOnline())
{
WebService webService = new WebService("http://liebenwald.spendino.net/admanager/dev/android/projects.json");
Map<String, String> params = new HashMap<String, String>();
params.put("var", "");
String response = webService.webGet("", params);
try
{
Type collectionType = new TypeToken<ArrayList<Project>>(){}.getType();
List<Project> lst= new Gson().fromJson(response, collectionType);
for(Project l : lst)
{
prjcts.add(l);
ConstantData.projectsList.add(l);
}
arrayAdapter.notifyDataSetChanged();
}
catch(Exception e)
{
Log.d("Error: ", e.getMessage());
}
}
lstTest.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent care = new Intent(ProjectsList.this, ProjectDetail.class);
care.putExtra("spendino.de.ProjectDetail.position",position);
startActivity(care);
}
});
}
#Override
public void onDestroy()
{
yAdapter.imageLoader.stopThread();
lstTest.setAdapter(null);
super.onDestroy();
}
protected boolean isOnline() {
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
if (netInfo != null && netInfo.isConnected()) {
return true;
} else {
}
});
return false;
}
}
}
Please advise if more of my codes are required.
Thanks
Look, you need to have the data in your application so that you can call them when no internet connection is available...
When you are getting the data save it somewhere in your application.Then pass the data in your Adapter..
The images will not be downloaded again...
In Fedor's lazylist the url of the images are static but here they are coming dynamically.
Hope this will help you.

Categories

Resources