Java tutorial
/* * Copyright 2013 Michael Boyde Wallace (http://wallaceit.com.au) * This file is part of Reddinator. * * Reddinator is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Reddinator is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Reddinator (COPYING). If not, see <http://www.gnu.org/licenses/>. */ package au.com.wallaceit.reddinator; import android.app.ActionBar; import android.app.Activity; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.preference.PreferenceManager; import android.text.Html; import android.view.View; import android.view.ViewGroup; import android.widget.AbsListView; import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; public class MainActivity extends Activity { private Context context; private SharedPreferences prefs; private GlobalObjects global; private ReddinatorListAdapter listAdapter; private AbsListView listView; private View appView; private ActionBar actionBar; private ProgressBar loader; private TextView srtext; private ImageView errorIcon; private ImageButton refreshbutton; private ImageButton configbutton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); context = MainActivity.this; global = ((GlobalObjects) context.getApplicationContext()); prefs = PreferenceManager.getDefaultSharedPreferences(context); setContentView(R.layout.activity_main); // Setup actionbar appView = findViewById(R.id.appview); actionBar = getActionBar(); if (actionBar != null) { actionBar.setDisplayShowHomeEnabled(false); actionBar.setDisplayShowCustomEnabled(true); actionBar.setDisplayShowTitleEnabled(false); actionBar.setCustomView(R.layout.appheader); } // get actionBar Views loader = (ProgressBar) findViewById(R.id.appsrloader); errorIcon = (ImageView) findViewById(R.id.apperroricon); refreshbutton = (ImageButton) findViewById(R.id.apprefreshbutton); configbutton = (ImageButton) findViewById(R.id.appprefsbutton); srtext = (TextView) findViewById(R.id.appsubreddittxt); // set theme colors setThemeColors(); // setup button onclicks refreshbutton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { listAdapter.reloadReddits(); } }); View.OnClickListener srclick = new View.OnClickListener() { @Override public void onClick(View view) { Intent srintent = new Intent(context, SubredditSelectActivity.class); startActivityForResult(srintent, 0); } }; View.OnClickListener configclick = new View.OnClickListener() { @Override public void onClick(View view) { Intent prefsintent = new Intent(context, PrefsActivity.class); prefsintent.putExtra("fromapp", true); startActivityForResult(prefsintent, 0); } }; srtext.setOnClickListener(srclick); configbutton.setOnClickListener(configclick); findViewById(R.id.app_logo).setOnClickListener(srclick); // Setup list adapter listView = (ListView) findViewById(R.id.applistview); listAdapter = new ReddinatorListAdapter(global, prefs); listView.setAdapter(listAdapter); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) { openLink(position, 1); } }); listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { @Override public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) { final int position = i; AlertDialog linkDialog = new AlertDialog.Builder(context).create(); //Read Update linkDialog.setTitle("Open in browser"); linkDialog.setButton(DialogInterface.BUTTON_POSITIVE, "Comments", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { openLink(position, 3); } }); linkDialog.setButton(DialogInterface.BUTTON_NEUTRAL, "Content", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { openLink(position, 2); } }); linkDialog.show(); return true; } }); // set the current subreddit srtext.setText(prefs.getString("currentfeed-app", "technology")); // Trigger reload? if (prefs.getBoolean("appreloadpref", false) || listAdapter.getCount() < 2) listAdapter.reloadReddits(); } @Override protected void onResume() { super.onResume(); Bundle update = global.getItemUpdate(); if (update != null) { listAdapter.updateUiVote(update.getInt("position", 0), update.getString("id"), update.getString("val")); } } private void setThemeColors() { int themenum = Integer.parseInt(PreferenceManager.getDefaultSharedPreferences(context) .getString(context.getString(R.string.widget_theme_pref), "1")); switch (themenum) { case 1: actionBar.getCustomView().setBackgroundDrawable(new ColorDrawable(Color.parseColor("#CEE3F8"))); appView.setBackgroundColor(Color.WHITE); configbutton.setBackgroundColor(Color.parseColor("#CEE3F8")); refreshbutton.setBackgroundColor(Color.parseColor("#CEE3F8")); errorIcon.setBackgroundColor(Color.parseColor("#CEE3F8")); srtext.setTextColor(Color.parseColor("#000000")); break; case 3: case 5: Drawable header = getResources().getDrawable(android.R.drawable.dark_header); actionBar.getCustomView().setBackgroundDrawable(header); appView.setBackgroundColor(Color.BLACK); configbutton.setBackgroundDrawable(null); refreshbutton.setBackgroundDrawable(null); errorIcon.setBackgroundDrawable(header); srtext.setTextColor(Color.parseColor("#FFFFFF")); break; case 4: case 2: actionBar.getCustomView().setBackgroundDrawable(new ColorDrawable(Color.parseColor("#5F99CF"))); appView.setBackgroundColor(Color.BLACK); configbutton.setBackgroundColor(Color.parseColor("#5F99CF")); refreshbutton.setBackgroundColor(Color.parseColor("#5F99CF")); errorIcon.setBackgroundColor(Color.parseColor("#5F99CF")); srtext.setTextColor(Color.parseColor("#000000")); break; } } @Override protected void onActivityResult(int reqcode, int resultcode, Intent data) { switch (resultcode) { case 1: // reload feed prefs listAdapter.loadFeedPrefs(); listView.invalidateViews(); break; case 2: // reload feed prefs and update feed, subreddit has changed srtext.setText(PreferenceManager.getDefaultSharedPreferences(context).getString("currentfeed-app", "technology")); listAdapter.loadFeedPrefs(); listAdapter.reloadReddits(); break; case 3: // reload theme setThemeColors(); listAdapter.loadAppPrefs(); listView.invalidateViews(); break; } } public void openLink(int position, int openType) { // get the item JSONObject item = listAdapter.getItem(position); switch (openType) { case 1: // open in the reddinator view Intent clickIntent1 = new Intent(context, ViewRedditActivity.class); Bundle extras = new Bundle(); try { extras.putString(WidgetProvider.ITEM_ID, item.getString("name")); extras.putInt("itemposition", position); extras.putString(WidgetProvider.ITEM_URL, item.getString("url")); extras.putString(WidgetProvider.ITEM_PERMALINK, item.getString("permalink")); } catch (JSONException e) { e.printStackTrace(); } clickIntent1.putExtras(extras); context.startActivity(clickIntent1); break; case 2: // open link in browser String url = null; try { url = item.getString("url"); } catch (JSONException e) { e.printStackTrace(); } Intent clickIntent2 = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); context.startActivity(clickIntent2); break; case 3: // open reddit comments page in browser String permalink = null; try { permalink = item.getString("permalink"); } catch (JSONException e) { e.printStackTrace(); } Intent clickIntent3 = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.reddit.com" + permalink)); context.startActivity(clickIntent3); break; } } public class ReddinatorListAdapter extends BaseAdapter { private JSONArray data; private GlobalObjects global; private SharedPreferences mSharedPreferences; private String titleFontSize = "16"; private int[] themeColors; private boolean loadThumbnails = false; private boolean bigThumbs = false; private boolean hideInf = false; protected ReddinatorListAdapter(GlobalObjects gobjects, SharedPreferences prefs) { global = gobjects; mSharedPreferences = prefs; // load the caches items data = global.getFeed(mSharedPreferences, 0); //System.out.println("cached Data length: "+data.length()); if (data.length() != 0) { titleFontSize = mSharedPreferences.getString("titlefontpref", "16"); try { lastItemId = data.getJSONObject(data.length() - 1).getJSONObject("data").getString("name"); } catch (JSONException e) { lastItemId = "0"; // Could not get last item ID; perform a reload next time and show error view :( e.printStackTrace(); } } // load preferences loadAppPrefs(); loadFeedPrefs(); } private void loadAppPrefs() { switch (Integer.valueOf(mSharedPreferences.getString("widgetthemepref", "1"))) { // set colors array: healine text, load more text, divider, domain text, vote & comments case 1: themeColors = new int[] { Color.BLACK, Color.BLACK, Color.parseColor("#D7D7D7"), Color.parseColor("#336699"), Color.parseColor("#FF4500") }; break; case 2: themeColors = new int[] { Color.WHITE, Color.WHITE, Color.parseColor("#646464"), Color.parseColor("#5F99CF"), Color.parseColor("#FF8B60") }; break; case 3: case 4: case 5: themeColors = new int[] { Color.WHITE, Color.WHITE, Color.parseColor("#646464"), Color.parseColor("#CEE3F8"), Color.parseColor("#FF8B60") }; break; } // user title color override if (!mSharedPreferences.getString("titlecolorpref", "0").equals("0")) { themeColors[0] = Color.parseColor(mSharedPreferences.getString("titlecolorpref", "#000")); } // get font size preference titleFontSize = mSharedPreferences.getString("titlefontpref", "16"); } private void loadFeedPrefs() { // get thumbnail load preference for the widget loadThumbnails = mSharedPreferences.getBoolean("thumbnails-app", true); bigThumbs = mSharedPreferences.getBoolean("bigthumbs-app", false); hideInf = mSharedPreferences.getBoolean("hideinf-app", false); } @Override public int getCount() { return (data.length() + 1); // plus 1 advertises the "load more" item to the listview without having to add it to the data source } @Override public View getView(final int position, View row, ViewGroup parent) { if (position > data.length()) { return null; // prevent errornous views } // check if its the last view and return loading view instead of normal row if (position == data.length()) { // build load more item View loadmorerow = getLayoutInflater().inflate(R.layout.listrowloadmore, parent, false); TextView loadtxtview = (TextView) loadmorerow.findViewById(R.id.loadmoretxt); if (endOfFeed) { loadtxtview.setText("There's nothing more here"); } else { loadtxtview.setText("Load more..."); } loadtxtview.setTextColor(themeColors[1]); loadmorerow.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { ((TextView) view.findViewById(R.id.loadmoretxt)).setText("Loading..."); loadMoreReddits(); } }); return loadmorerow; } else { // inflate new view or load view holder if existing ViewHolder viewHolder = new ViewHolder(); if (row == null || row.getTag() == null) { // create remote view from specified layout if (bigThumbs) { row = getLayoutInflater().inflate(R.layout.applistrowbigthumb, parent, false); } else { row = getLayoutInflater().inflate(R.layout.applistrow, parent, false); } viewHolder.listheading = (TextView) row.findViewById(R.id.listheading); viewHolder.sourcetxt = (TextView) row.findViewById(R.id.sourcetxt); viewHolder.votestxt = (TextView) row.findViewById(R.id.votestxt); viewHolder.commentstxt = (TextView) row.findViewById(R.id.commentstxt); viewHolder.thumbview = (ImageView) row.findViewById(R.id.thumbnail); viewHolder.infview = row.findViewById(R.id.infbox); viewHolder.upvotebtn = (ImageButton) row.findViewById(R.id.app_upvote); viewHolder.downvotebtn = (ImageButton) row.findViewById(R.id.app_downvote); viewHolder.nsfw = (TextView) row.findViewById(R.id.nsfwflag); } else { viewHolder = (ViewHolder) row.getTag(); } // collect data String name = ""; String thumbnail = ""; String domain = ""; String id = ""; String userLikes = "null"; int score = 0; int numcomments = 0; boolean nsfw = false; try { JSONObject tempobj = data.getJSONObject(position).getJSONObject("data"); name = tempobj.getString("title"); id = tempobj.getString("name"); domain = tempobj.getString("domain"); thumbnail = (String) tempobj.get("thumbnail"); // we have to call get and cast cause its not in quotes score = tempobj.getInt("score"); numcomments = tempobj.getInt("num_comments"); userLikes = tempobj.getString("likes"); nsfw = tempobj.getBoolean("over_18"); } catch (JSONException e) { e.printStackTrace(); // return null; // The view is invalid; } // Update view viewHolder.listheading.setText(Html.fromHtml(name).toString()); viewHolder.listheading.setTextSize(Integer.valueOf(titleFontSize)); // use for compatibility setTextViewTextSize only introduced in API 16 viewHolder.listheading.setTextColor(themeColors[0]); viewHolder.sourcetxt.setText(domain); viewHolder.sourcetxt.setTextColor(themeColors[3]); viewHolder.votestxt.setText(String.valueOf(score)); viewHolder.votestxt.setTextColor(themeColors[4]); viewHolder.commentstxt.setText(String.valueOf(numcomments)); viewHolder.commentstxt.setTextColor(themeColors[4]); viewHolder.nsfw.setVisibility((nsfw ? TextView.VISIBLE : TextView.GONE)); row.findViewById(R.id.listdivider).setBackgroundColor(themeColors[2]); // set vote button if (!userLikes.equals("null")) { if (userLikes.equals("true")) { viewHolder.upvotebtn.setImageResource(R.drawable.upvote_active); viewHolder.downvotebtn.setImageResource(R.drawable.downvote); } else { viewHolder.upvotebtn.setImageResource(R.drawable.upvote); viewHolder.downvotebtn.setImageResource(R.drawable.downvote_active); } } else { viewHolder.upvotebtn.setImageResource(R.drawable.upvote); viewHolder.downvotebtn.setImageResource(R.drawable.downvote); } // Set vote onclick listeners viewHolder.upvotebtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { listAdapter.showAppLoader(); view = (View) view.getParent().getParent(); ListVoteTask listvote = new ListVoteTask(1, view, position); listvote.execute(); } }); viewHolder.downvotebtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { listAdapter.showAppLoader(); view = (View) view.getParent().getParent(); ListVoteTask listvote = new ListVoteTask(-1, view, position); listvote.execute(); } }); // load thumbnail if they are enabled for this widget if (loadThumbnails) { // load big image if preference is set if (!thumbnail.equals("")) { // check for thumbnail; self is used to display the thinking logo on the reddit site, we'll just show nothing for now if (thumbnail.equals("nsfw") || thumbnail.equals("self") || thumbnail.equals("default")) { int resource = 0; switch (thumbnail) { case "nsfw": resource = R.drawable.nsfw; break; case "default": case "self": resource = R.drawable.self_default; break; } viewHolder.thumbview.setImageResource(resource); viewHolder.thumbview.setVisibility(View.VISIBLE); //System.out.println("Loading default image: "+thumbnail); } else { // check if the image is in cache String fileurl = getCacheDir() + "/thumbcache-app/" + id + ".png"; if (new File(fileurl).exists()) { Bitmap bitmap = BitmapFactory.decodeFile(fileurl); if (bitmap == null) { viewHolder.thumbview.setVisibility(View.GONE); } else { viewHolder.thumbview.setImageBitmap(bitmap); viewHolder.thumbview.setVisibility(View.VISIBLE); } } else { // start the image load loadImage(position, thumbnail, id); viewHolder.thumbview.setVisibility(View.VISIBLE); // set image source as default to prevent an image from a previous view being used viewHolder.thumbview .setImageResource(android.R.drawable.screen_background_dark_transparent); } } } else { viewHolder.thumbview.setVisibility(View.GONE); } } else { viewHolder.thumbview.setVisibility(View.GONE); } // hide info bar if options set if (hideInf) { viewHolder.infview.setVisibility(View.GONE); } else { viewHolder.infview.setVisibility(View.VISIBLE); } row.setTag(viewHolder); } //System.out.println("getViewAt("+position+");"); return row; } @Override public JSONObject getItem(int position) { try { return data.getJSONObject(position).getJSONObject("data"); } catch (JSONException e) { e.printStackTrace(); return null; } } public void updateUiVote(int position, String id, String val) { try { // Incase the feed updated after opening reddinator view, check that the id's match to update the correct view. boolean recordexists = data.getJSONObject(position).getJSONObject("data").getString("name") .equals(id); if (recordexists) { // update in current data (already updated in saved feed) data.getJSONObject(position).getJSONObject("data").put("likes", val); // refresh view; unfortunately we have to refresh them all :( invalidateViewAtPosition(); please android? listView.invalidateViews(); } } catch (JSONException e) { e.printStackTrace(); } } private void loadImage(final int itempos, final String urlstr, final String redditid) { new ImageLoader(itempos, urlstr, redditid).execute(); } private void clearImageCache() { // delete all images in the cache folder. DeleteRecursive(new File(getCacheDir() + "/thumbcache-app")); } @SuppressWarnings("ResultOfMethodCallIgnored") private void DeleteRecursive(File fileOrDirectory) { if (fileOrDirectory.isDirectory()) for (File child : fileOrDirectory.listFiles()) DeleteRecursive(child); fileOrDirectory.delete(); } @SuppressWarnings("ResultOfMethodCallIgnored") private boolean saveImageToStorage(Bitmap image, String redditid) { try { File file = new File(context.getCacheDir().getPath() + "/thumbcache-app/", redditid + ".png"); if (!file.getParentFile().exists()) { file.getParentFile().mkdirs(); } FileOutputStream fos = new FileOutputStream(file); image.compress(Bitmap.CompressFormat.PNG, 100, fos); // 100 means no compression, the lower you go, the stronger the compression fos.close(); return true; } catch (Exception e) { return false; } } class ViewHolder { TextView listheading; TextView sourcetxt; TextView votestxt; TextView commentstxt; ImageView thumbview; ImageButton upvotebtn; ImageButton downvotebtn; View infview; TextView nsfw; } class ImageLoader extends AsyncTask<Void, Integer, Bitmap> { int itempos; String urlstr; String redditid; ImageLoader(int position, String url, String id) { itempos = position; urlstr = url; redditid = id; } @Override protected Bitmap doInBackground(Void... voids) { URL url; try { url = new URL(urlstr); URLConnection con = url.openConnection(); con.setConnectTimeout(8000); con.setReadTimeout(8000); return BitmapFactory.decodeStream(con.getInputStream()); } catch (MalformedURLException e) { e.printStackTrace(); return null; } catch (IOException e) { e.printStackTrace(); return null; } } @Override protected void onPostExecute(Bitmap result) { View v = listView.getChildAt(itempos - listView.getFirstVisiblePosition()); if (v == null) { return; } // save bitmap to cache, the item name will be the reddit id saveImageToStorage(result, redditid); // update view if it's being shown ImageView img = ((ImageView) v.findViewById(R.id.thumbnail)); if (img != null) { if (result != null) { img.setImageBitmap(result); } else { img.setVisibility(View.GONE); } } } } @Override public int getViewTypeCount() { return (3); } @Override public long getItemId(int position) { return (position); } @Override public boolean hasStableIds() { return (false); } private String lastItemId = "0"; private boolean endOfFeed = false; public void loadMoreReddits() { loadReddits(true); } public void reloadReddits() { clearImageCache(); loadReddits(false); } private void loadReddits(boolean loadMore) { showAppLoader(); new FeedLoader(loadMore).execute(); } class FeedLoader extends AsyncTask<Void, Integer, Long> { private Boolean loadMore; public FeedLoader(Boolean loadmore) { loadMore = loadmore; } @Override protected Long doInBackground(Void... none) { String curFeed = mSharedPreferences.getString("currentfeed-app", "technology"); // System.out.println("Current feed: " + curFeed); String sort = mSharedPreferences.getString("sort-app", "hot"); if (loadMore) { // fetch 25 more after current last item and append to the list JSONArray tempData = global.mRedditData.getRedditFeed(curFeed, sort, 25, lastItemId); if (!isError(tempData)) { if (tempData.length() == 0) { endOfFeed = true; } else { endOfFeed = false; int i = 0; while (i < tempData.length()) { try { data.put(tempData.get(i)); } catch (JSONException e) { e.printStackTrace(); } i++; } // save feed global.setFeed(prefs, 0, data); } } else { return (long) 0; } } else { endOfFeed = false; // reloading int limit = Integer.valueOf(mSharedPreferences.getString("numitemloadpref", "25")); JSONArray tempArray = global.mRedditData.getRedditFeed(curFeed, sort, limit, "0"); // check if data is valid; if the getredditfeed function fails to create a connection it returns -1 in the first value of the array if (!isError(tempArray)) { data = tempArray; if (data.length() == 0) { endOfFeed = true; } // save feed global.setFeed(prefs, 0, data); } else { return (long) 0; } } try { lastItemId = data.getJSONObject(data.length() - 1).getJSONObject("data").getString("name"); // name is actually the unique id we want } catch (JSONException e) { lastItemId = "0"; // Could not get last item ID; perform a reload next time and show error view :( e.printStackTrace(); } return (long) 1; } @Override protected void onPostExecute(Long result) { if (result > 0) { // hide loader if (loadMore) { hideAppLoader(false, false); // don't go to top of list } else { hideAppLoader(true, false); // go to top } listAdapter.notifyDataSetChanged(); } else { hideAppLoader(false, true); // don't go to top of list and show error icon } } // check if the array is an error array private boolean isError(JSONArray tempArray) { boolean error; if (tempArray == null) { return true; // null error } if (tempArray.length() > 0) { try { error = tempArray.getString(0).equals("-1"); } catch (JSONException e) { error = true; e.printStackTrace(); } } else { error = false; // empty array means no more feed items } return error; } } class ListVoteTask extends AsyncTask<String, Integer, String> { JSONObject item; private String redditid; private int direction; private String curVote; private int listposition; private ImageButton upvotebtn; private ImageButton downvotebtn; public ListVoteTask(int dir, View view, int position) { direction = dir; upvotebtn = (ImageButton) view.findViewById(R.id.app_upvote); downvotebtn = (ImageButton) view.findViewById(R.id.app_downvote); // Get data by position in list listposition = position; item = listAdapter.getItem(listposition); try { redditid = item.getString("name"); curVote = item.getString("likes"); } catch (JSONException e) { redditid = "null"; curVote = "null"; } } @Override protected String doInBackground(String... strings) { // enumerate current vote and clicked direction if (direction == 1) { if (curVote.equals("true")) { // if already upvoted, neutralize. direction = 0; } } else { // downvote if (curVote.equals("false")) { direction = 0; } } // Do the vote try { return global.mRedditData.vote(redditid, direction); } catch (RedditData.RedditApiException e) { e.printStackTrace(); return e.getMessage(); } } @Override protected void onPostExecute(String result) { if (result.equals("OK")) { // set icon + current "likes" in the data array, this way ViewRedditActivity will get the new version without updating the hole feed. String value = "null"; switch (direction) { case -1: upvotebtn.setImageResource(R.drawable.upvote); downvotebtn.setImageResource(R.drawable.downvote_active); value = "false"; break; case 0: upvotebtn.setImageResource(R.drawable.upvote); downvotebtn.setImageResource(R.drawable.downvote); value = "null"; break; case 1: upvotebtn.setImageResource(R.drawable.upvote_active); downvotebtn.setImageResource(R.drawable.downvote); value = "true"; break; } listAdapter.updateUiVote(listposition, redditid, value); global.setItemVote(prefs, 0, listposition, redditid, value); } else if (result.equals("LOGIN")) { global.mRedditData.initiateLogin(MainActivity.this); } else { // show error Toast.makeText(MainActivity.this, "API Error: " + result, Toast.LENGTH_LONG).show(); } listAdapter.hideAppLoader(false, false); } } // hide loader private void hideAppLoader(boolean goToTopOfList, boolean showError) { // get theme layout id loader.setVisibility(View.GONE); // go to the top of the list view if (goToTopOfList) { listView.smoothScrollToPosition(0); } if (showError) { errorIcon.setVisibility(View.VISIBLE); } } private void showAppLoader() { errorIcon.setVisibility(View.GONE); loader.setVisibility(View.VISIBLE); } } }