Calling an AsyncTask from another asynctask in doInBackground method? - java

I have AsyncTask2 called from AsyncTask1... that's my 'scenario':
AsyncTask1 download an rss feed, parse the xml and for every item recognized create&execute AsyncTask2 inside the doInBackground method.
AsyncTask2 in the doInBackground method download the enclosure url attribute of the item passed from AsyncTask1 and in onPostExecute method add the item to the global items array and notify the change of items to the associated adapter.
It works fine and not crashing, why? AsyncTasks are supposed to run from the UI thread (threading rules) and now I'm a little confused about this supposition.
Sorry for bad english, I hope question is clear enough.
EDIT
Here some code...
DownloadRssAsyncTask = AsyncTask2,
RssAsyncTask = AsyncTask1
public class ParseActivity extends Activity {
public class FeedItemAdapter extends ArrayAdapter<FeedItem> {
int resource;
public FeedItemAdapter(Context context, int resource, List<FeedItem> items) {
super(context, resource, items);
this.resource = resource;
}
public View getView(int position, View convertView, ViewGroup parent) {
LinearLayout myView;
FeedItem item = getItem(position);
if (convertView == null) {
myView = new LinearLayout(getContext());
String inflaterService = Context.LAYOUT_INFLATER_SERVICE;
LayoutInflater li = (LayoutInflater) getContext().getSystemService(inflaterService);
li.inflate(resource, myView, true);
} else {
myView = (LinearLayout) convertView;
}
TextView titleFeedItem = (TextView) myView.findViewById(R.id.itemTitle);
TextView dateFeedItem = (TextView) myView.findViewById(R.id.itemDate);
ImageView imageFeedItem = (ImageView) myView.findViewById(R.id.imageThumb);
titleFeedItem.setText(item.mTitle);
dateFeedItem.setText(item.mPubDate);
imageFeedItem.setImageBitmap(item.bitmapEnclosure);
return myView;
}
}
private class DownloadRssAsyncTask extends AsyncTask<FeedItem, Void, FeedItem> {
#Override
protected FeedItem doInBackground(FeedItem... params) {
FeedItem item = params[0];
if (item.mEnclosure == null) {
Log.i("info: ", "no enclosure tag");
item.bitmapEnclosure = null;
return item;
}
try {
URL imageUrl = new URL(item.mEnclosure);
item.bitmapEnclosure = BitmapFactory.decodeStream(imageUrl.openStream());
} catch (IOException e) {
Log.e("error", "download image resource error: "+item.mEnclosure);
item.bitmapEnclosure = null;
}
return item;
}
#Override
protected void onPostExecute(FeedItem result) {
items.add(result);
arrayAdapter.notifyDataSetChanged();
dbHelper.putItem(result.mGuid, result.mTitle, result.mDescription, result.mEnclosure, result.mPubDate);
}
}
private class RssAsyncTask extends AsyncTask<String, Integer, Void> {
#Override
protected Void doInBackground(String... params) {
int dimParams = params.length;
for (int i=0; i<dimParams; i++) {
Log.i("doInBackground", "rss feed num "+ (i+1) + " of "+ dimParams+ ": " + params[i]);
refreshFeed(params[i]);
}
return null;
}
#Override
protected void onPostExecute(Void result) {
Log.i("onPostExecute in RssAsyncTask", "notifyDataSetChanged");
}
}
public static class FeedItem {
public String mAuthor;
public String mCategory;
public String mComments;
public String mDescription; //r
public String mEnclosure;
public Bitmap bitmapEnclosure;
public String mGuid;
public String mLink; //r
public String mPubDate;
public String mSource;
public String mTitle; //r
public FeedItem() {
// TODO Auto-generated constructor stub
}
#Override
public String toString() {
return
"Data: "+mPubDate+
"\nLink:\n"+mLink+
"\nAutore:\n"+mAuthor+
"\nTitolo:\n"+mTitle+
"\nEnclosure:\n"+mEnclosure;
}
}
private FeedReaderDbHelper dbHelper;
private FeedItemAdapter arrayAdapter;
private ArrayList<FeedItem> items;
private ListView myListView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_parse);
items = new ArrayList<FeedItem>();
new ArrayList<FeedItem>();
myListView = (ListView) findViewById(R.id.myListView);
arrayAdapter = new FeedItemAdapter(this, R.layout.feed_item, items);
myListView.setAdapter(arrayAdapter);
dbHelper = new FeedReaderDbHelper(this);
//RssAsyncTask: download and parsing rss feed
new RssAsyncTask().execute(getString(R.string.my_feed));
}
public void refreshFeed(String feed) {
final String TAG = "refreshFeed";
Log.i(TAG, feed);
URL url = null;
try {
url = new URL(feed);
HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();
int httpCode = httpConnection.getResponseCode();
if (httpCode == HttpURLConnection.HTTP_OK) {
processFeed(httpConnection.getInputStream());
} else {
Log.i(TAG, httpCode + httpConnection.getResponseMessage());
}
} catch (MalformedURLException e1) {
Log.i(TAG, "MalformedUrlException in " + feed);
} catch (IOException e) {
Log.i(TAG, "IOException in " + url.toString());
}
}
private void processFeed(InputStream inputStream ) {
final String TAG = "processFeed";
final String ITEM = "item";
final String AUTHOR ="author";
final String TITLE ="title";
final String CATEGORY ="category";
final String COMMENTS ="comments";
final String DESCRIPTION ="description";
final String GUID ="guid";
final String LINK ="link";
final String PUBDATE="pubDate";
final String SOURCE ="source";
final String ENCLOSURE = "enclosure";
Log.i(TAG, inputStream.toString());
XmlPullParserFactory pullParserFact;
try {
pullParserFact = XmlPullParserFactory.newInstance();
pullParserFact.setNamespaceAware(true);
XmlPullParser pullParser = pullParserFact.newPullParser();
pullParser.setInput(inputStream, null);
int eventType = pullParser.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG && pullParser.getName().equals(ITEM)){
final FeedItem item = new FeedItem();
eventType = pullParser.next();
while ( !(eventType == XmlPullParser.END_TAG && pullParser.getName().equals(ITEM)) ) {
if ( eventType == XmlPullParser.START_TAG ) {
String name = pullParser.getName();
switch (name) {
case AUTHOR:
item.mAuthor = pullParser.nextText();
break;
case TITLE:
item.mTitle = pullParser.nextText();
break;
case CATEGORY:
item.mCategory = pullParser.nextText();
break;
case COMMENTS:
item.mComments = pullParser.nextText();
break;
case DESCRIPTION:
item.mDescription = pullParser.nextText();
break;
case GUID:
item.mGuid = pullParser.nextText();
break;
case LINK:
item.mLink = pullParser.nextText();
break;
case PUBDATE:
item.mPubDate = pullParser.nextText();
break;
case SOURCE:
item.mSource = pullParser.nextText();
break;
case ENCLOSURE:
item.mEnclosure = pullParser.getAttributeValue(null, "url");
default:
break;
}
}
eventType = pullParser.next();
}
//download the optional enclosure resource and update UI
new DownloadRssAsyncTask().execute(item);
}
eventType = pullParser.next();
}
} catch (XmlPullParserException e) {
Log.i(TAG, "XmlPullparserException");
} catch (IOException e) {
Log.i(TAG, "IOException");
}
}
}

Because of the inner workings of AsyncTask.
AsyncTask internally uses a static Handler instance, basically the Android way for thread communication. With a Handler you can send messages and run code on threads; in particular, AsyncTask uses it to run its callbacks such as onPostExecute().
Now, when Handler is initialiazed, it binds on the thread that initializes it. In AsyncTask this is done during class initialization/loading at the line:
private static final InternalHandler sHandler = new InternalHandler();
Since sHandler is also final, it cannot be modified after that, and the callbacks will be always triggered on that thread.
In your case, you create an instance of RssAsyncTask in onCreate(), which is run on the UI thread. This triggers the loading of the AsyncTask class and bind AsyncTask's Handler to the UI thread. Therefore, from that point your onPostExecute()s will always be run on the UI Thread. This is despite you create some AsyncTasks in another background thread.
The Threading Rules want to ensure the class is loaded/initialized on the UI thread (see this) and want to enforce good threading practices.
Also, I recommend IntentService for simple network operations, rather than AsyncTask.

Related

Define text color based on value using AsyncTask

So basically my AsyncTask get the value from the url and when i execute i wanna show green text or red text if contains ("-").
I have search around and none of the option worked for me. i do have a RecyclerView.ViewHolder but don't know how to incorporate before i execute. Everything works, except the colors.
Thank you in advance
Activity
public class BTCData extends AsyncTask<Void,RecyclerView.ViewHolder,Void> {
String data = "";
String dataParsed1h ="";
String dataParsed24h ="";
String dataParsed7d ="";
String percent_change_1h = "";
String percent_change_24h = "";
String percent_change_7d = "";
Activity activity;
List<Model> items;
public BTCData() {
}
#Override
protected Void doInBackground(Void... voids) {
try {
URL url = new URL ("https://...");
HttpURLConnection httpURLConnection = (java.net.HttpURLConnection) url.openConnection();
InputStream inputStream = httpURLConnection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String line = "";
while (line != null){
line = bufferedReader.readLine();
data = data+line;
}
JSONArray JA = new JSONArray(data);
for(int i=0 ;i< JA.length(); i++){
JSONObject JO = (JSONObject) JA.get(i);
percent_change_1h = "1H " + JO.getString("percent_change_1h") + "%";
percent_change_24h = "24H " + JO.getString("percent_change_24h") + "%";
percent_change_7d = "7D " + JO.getString("percent_change_7d") + "%" ;
dataParsed1h = dataParsed1h + percent_change_1h;
dataParsed24h = dataParsed24h + percent_change_7d;
dataParsed7d = dataParsed7d + percent_change_24h;
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
MainActivity.btc_percent_change_1h.setText(this.dataParsed1h);
MainActivity.btc_percent_change_24h.setText(this.dataParsed24h);
MainActivity.btc_percent_change_7d.setText(this.dataParsed7d);
}
}```
**View Holder**
public class CoinAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
Adapter adapter;
boolean isLoading;
Activity activity;
List<Model> items;
int visibleThreshold = 5,lastVisibleItem, totalItemcount;
public void setAdapter(Adapter adapter) {
this.adapter = adapter;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(activity)
.inflate(R.layout.activity_main,parent,false);
return new CoinViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
Model item = items.get(position);
CoinViewHolder holderItem = (CoinViewHolder)holder;
holderItem.btc_percent_change_1h.setTextColor(item.getPercentage_change_1h().contains("-")?
Color.parseColor("#FF0000"):Color.parseColor("#32CD32"));
holderItem.btc_percent_change_24h.setTextColor(item.getPercentage_change_24h().contains("-")?
Color.parseColor("#FF0000"):Color.parseColor("#32CD32"));
holderItem.btc_percent_change_7d.setTextColor(item.getPercentage_change_7d().contains("-")?
Color.parseColor("#FF0000"):Color.parseColor("#32CD32"));
}
#Override
public int getItemCount() {
return items.size();
}
public void setLoader() {isLoading = true;}
public void updateData (List<Model> models)
{
this.items = models;
notifyDataSetChanged();
}
**on Activity**
public static TextView btc_percent_change_1h;
public static TextView btc_percent_change_24h;
public static TextView btc_percent_change_7d;
//Percentage
btc_percent_change_1h = (TextView) findViewById(R.id.btc_percent_change_1h);
btc_percent_change_24h = (TextView) findViewById(R.id.btc_percent_change_24h);
btc_percent_change_7d = (TextView) findViewById(R.id.btc_percent_change_7d);
and finally call...
BTCData process = new BTCData();
process.execute();
This is because for setting color you are doing in onBindViewHolder when in that case data would be 0 only without red sign and later you are setting data but after that onBindViewHolder is not called and hence changes are not reflecting.
The way you are doing all this is not ideal way and would suggest you to read design patterns to implement it in proper way.
Maybe is not the best option, but it works
#Override
protected void onPostExecute(CoinAdapter aVoid) {
super.onPostExecute(aVoid);
MainActivity.btc_percent_change_1h.setTextColor((this.dataParsed1h.contains("-")?
Color.parseColor("#FF0000"):Color.parseColor("#32CD32")));
MainActivity.btc_percent_change_1h.setText(this.dataParsed1h);
MainActivity.btc_percent_change_24h.setTextColor((this.dataParsed24h.contains("-")?
Color.parseColor("#FF0000"):Color.parseColor("#32CD32")));
MainActivity.btc_percent_change_24h.setText(this.dataParsed24h);
MainActivity.btc_percent_change_7d.setTextColor((this.dataParsed7d.contains("-")?
Color.parseColor("#FF0000"):Color.parseColor("#32CD32")));
MainActivity.btc_percent_change_7d.setText(this.dataParsed7d);
}
You can achieve it like. Get value in adapter according to position and change it color like this. Then cocatinate both string and show it. You can test it on multiple devices it will run and show exact in every devices.
String status = getColoredSpanned(act.getResources().getString(R.string.order_status),"#3EA7BD");
String variable_status =getColoredSpanned(act.getResources().getString(R.string.status_order_pending),"#E23941");
String text = status+variable_status;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
myViewHolder.tv_order_product_status.setText(Html.fromHtml(text, Html.FROM_HTML_MODE_LEGACY), TextView.BufferType.SPANNABLE);
} else {
myViewHolder.tv_order_product_status.setText(Html.fromHtml(text), TextView.BufferType.SPANNABLE);
}

loading images to a recyclerview using a thread

So I have a Recyclerview which holding items with images, I want to load images into the items but when I do that I got a lot of fps drops.
I read that I need to use another thread for the network part and I tried to do that as you can see, and it seems good to me but I can't figure out how to stop the fps drops and make the scrolling in the Recyclerview smooth, this Recyclerview supposed to hold between 10 and 100. Am I supposed to run the activity in a thread?
Note: The fps drops occur with 10 items.
calling to the HttpWrapper.LoadImageFromWebOperations function in OnBindViewHolder.
HomeAdapter.java
public class HomeAdapter extends RecyclerView.Adapter<HomeAdapter.HomeViewHolder>{
private Context context;
private ArrayList<RecipeModel> items;
public HomeAdapter(Context context, ArrayList<RecipeModel> items) {
this.context = context;
this.items = items;
}
#Override
public HomeAdapter.HomeViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
View v = inflater.inflate(R.layout.home_item,null);
HomeAdapter.HomeViewHolder holder = new HomeAdapter.HomeViewHolder(v);
return holder;
}
public void addItem(RecipeModel item){
this.items.add(item);
notifyDataSetChanged();
}
#Override
public void onBindViewHolder(HomeAdapter.HomeViewHolder holder, final int position) {
RecipeModel model = items.get(position);
holder.name.setText(model.getName());
holder.directions.setText(model.getDirections()[0]);
Drawable drawable = HttpWrapper.LoadImageFromWebOperations(model.getImageSource());
holder.image.setImageDrawable(drawable);
}
#Override
public int getItemCount() {
return items.size();
}
class HomeViewHolder extends RecyclerView.ViewHolder{
TextView name;
TextView directions;
ImageView image;
public HomeViewHolder(View itemView) {
super(itemView);
name = (TextView) itemView.findViewById(R.id.recipe_name);
directions = (TextView) itemView.findViewById(R.id.recipe_directions);
image = (ImageView) itemView.findViewById(R.id.recipe_image);
}
}
HttpWrapper.java
public class HttpWrapper {
String responseMsg = "";
private OkHttpClient client;
private Request request;
public static final String base_url = "http://kingtimmy.pythonanywhere.com";
public static final String home_route = "/home/";
public HttpWrapper() {
client = new OkHttpClient();
}
public ArrayList<RecipeModel> get_home_recipes(int recipe_num){
ArrayList<RecipeModel> models = new ArrayList<RecipeModel>();
request = new Request.Builder().url(base_url + home_route + String.valueOf(recipe_num)).build();
responseMsg = "";
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
responseMsg = "Error: " + e.getMessage();
}
#Override
public void onResponse(Call call, Response response) throws IOException {
responseMsg = response.body().string();
}
});
while(responseMsg.equals("")){
continue;
}
String[] jsons = responseMsg.split("]-]");
for (int i = 0; i < jsons.length; i++){
models.add(makeRecipeModel(jsons[i]));
}
return models;
}
public RecipeModel makeRecipeModel(String msg){
JSONObject nodeRoot = null;
RecipeModel model;
try {
nodeRoot = new JSONObject(msg);
String[] directions = nodeRoot.get("directions").toString().split("\\n");
String[] ingredients = nodeRoot.get("ingredients").toString().split("\\n");
String image_source = nodeRoot.get("image").toString();
String source_url = nodeRoot.get("source_url").toString();
String name = nodeRoot.get("name").toString();
int id = Integer.valueOf(nodeRoot.get("id").toString());
model = new RecipeModel(directions,ingredients,image_source,source_url,name,id);
} catch (JSONException e) {
model = null;
}
return model;
}
public static Drawable LoadImageFromWebOperations(final String url) {
ExecutorService executor = Executors.newSingleThreadExecutor();
Callable<Drawable> callable = new Callable<Drawable>() {
#Override
public Drawable call() {
try {
InputStream is = (InputStream) new URL(url).getContent();
Drawable d = Drawable.createFromStream(is, "src name");
return d;
} catch (Exception e) {
System.out.println("Exc=" + e);
return null;
}
}
};
Future<Drawable> future = executor.submit(callable);
// future.get() returns 2 or raises an exception if the thread dies, so safer
try {
Drawable d = future.get();
executor.shutdown();
return d;
} catch (Exception e) {
return null;
}
}
What am I doing wrong?
Instead of writing your own thread and code to fetch, parse, decode and load the image, give Glide a try. It does all that for you with a simple single line code and loads the image in your ImageView

ArrayList doesn't display value outside of method where the data storing happens

I have this class where it process XML and store it inside an ArrayList<FeedItem>. I can display the array content in the method where I store the data but when I try to display the array in another method it did not pass the if checking indicating that the ArrayList is empty. Because of this, I can't create a ListView because it'll return the same error. I hope someone can briefly explain to me what is wrong.
ReadRSS.java
public class ReadRSS extends AsyncTask<Void, Void, Void> {
//Initialize progress dialog
Context context;
String address;
ProgressDialog progressDialog;
XmlPullParserFactory xmlPullParserFactory;
volatile boolean parsingComplete = true;
ArrayList<FeedItem> feedItems;
ListView listView;
public ReadRSS(Context context, ListView listView, String retrieveAddress) {
//Create a new progress dialog
this.listView = listView;
this.address = retrieveAddress;
this.context = context;
progressDialog = new ProgressDialog(context);
progressDialog.setMessage("Loading....");
}
// Runs in UI before background thread is called
#Override
protected void onPreExecute() {
//Display progress dialog
progressDialog.show();
super.onPreExecute();
}
// This is run in a background thread
#Override
protected Void doInBackground(Void... voids) {
fetchXML();
return null;
}
// This is called from background thread but runs in UI
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
// This runs in UI when background thread finishes
#Override
protected void onPostExecute(Void aVoid) {
//Dismiss progress dialog
super.onPostExecute(aVoid);
progressDialog.dismiss();
/*if(listView != null) {
CustomAdapter customAdapter = new CustomAdapter(context, R.layout.activity_listview, feedItems);
listView.setAdapter(customAdapter);
}*/
if(feedItems != null){
//Gives error
for(int i = 0; i < feedItems.size(); i++) {
Log.d("Title", feedItems.get(i).getTitle());
Log.d("Date", feedItems.get(i).getPubDate());
}
}
}
//New Build
public void parseXMLAndStoreIt(XmlPullParser myParser) {
int event;
String text;
String title = null;
String date = null;
feedItems = new ArrayList<FeedItem>();
try {
event = myParser.getEventType();
while (event != XmlPullParser.END_DOCUMENT) {
String tagName = myParser.getName();
switch (event){
case XmlPullParser.START_TAG:
if(tagName.equalsIgnoreCase("item")){
int eventChild = myParser.next();
//int innerLoop = 1;
String tagNameChild = "";
while(eventChild != XmlPullParser.END_DOCUMENT){
if(eventChild == XmlPullParser.START_TAG){
tagNameChild = myParser.getName();
// Output Test
//Log.d("Tag ", tagNameChild);
}
else if (eventChild == XmlPullParser.TEXT){
text = myParser.getText();
// Output Test
//Log.d("Test ", text);
if(tagNameChild.equalsIgnoreCase("title")){
title = text;
// Output Test
//Log.d("Title ", myParser.getText());
}
else if(tagNameChild.equalsIgnoreCase("pubDate")){
date = text;
// Output Test
//Log.d("PubDate ", myParser.getText());
}
}
else if (eventChild == XmlPullParser.END_TAG){
if(myParser.getName().equalsIgnoreCase("item")){
feedItems.add(new FeedItem(title,date));
// Output Test
//Log.d("Test ", title);
}
tagNameChild = "";
}
eventChild = myParser.next();
//innerLoop++;
}
//Output Test
/*for(int i = 0; i < feedItems.size(); i++) {
Log.d("Title", feedItems.get(i).getTitle());
Log.d("Date", feedItems.get(i).getPubDate());
}*/
}
break;
case XmlPullParser.TEXT:
break;
case XmlPullParser.END_TAG:
break;
}
event = myParser.next();
}
parsingComplete = false;
}
catch (Exception e) {
e.printStackTrace();
}
}
public void fetchXML(){
Thread thread = new Thread(new Runnable(){
#Override
public void run() {
try {
URL url = new URL(address);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000 );
conn.setConnectTimeout(15000 );
conn.setRequestMethod("GET");
conn.setDoInput(true);
// Starts the query
conn.connect();
InputStream stream = conn.getInputStream();
xmlPullParserFactory = XmlPullParserFactory.newInstance();
XmlPullParser myparser = xmlPullParserFactory.newPullParser();
myparser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
myparser.setInput(stream, null);
parseXMLAndStoreIt(myparser);
stream.close();
}
catch (Exception e) {
}
}
});
thread.start();
}
}
You are calling fetchXML() from doInBackground, but fetchXML() starts a new thread and then immediately returns. Then doInBackground() immediately returns and onPostExecute() is called. However, at that point, the thread launched by fetchXML() has not had time to finish, so feedItems has not been properly set.
That's the wrong way to use an AsyncTask. Instead, you should do the fetching directly in the doInBackground() thread. Just rewrite fetchXML() to do the fetching itself, rather than launch a separate thread to do the fetching.

Swipe Refresh freezes when executing async task

I'm encountering a problem, when I try running an asynchronous task on refresh using a swipe refresh layout it "freezes" and doesn't rotate. When the task is done it just disappears.
Here is my code:
HotActivityFragment.java:
public class HotActivityFragment extends Fragment {
ListView hotList;
SwipeRefreshLayout mSwipeRefreshLayout;
Context context;
SharedPreferences sharedPreferences;
HotListAdapter hotListAdapter;
public HotActivityFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_hot, container, false);
context = getContext();
mSwipeRefreshLayout = (SwipeRefreshLayout)view.findViewById(R.id.activity_main_swipe_refresh_layout);
hotList = (ListView)view.findViewById(R.id.hotListView);
hotList.setOnScrollListener(new EndlessScrollListener(getActivity()));
sharedPreferences = getActivity().getPreferences(Context.MODE_PRIVATE);
try {
ArrayList<ListTypeItem> initial_list = new DownloadPosts(getActivity()).execute().get();
this.hotListAdapter = new HotListAdapter(getContext(), initial_list);
hotList.setAdapter(hotListAdapter);
}catch(Exception e)
{
Log.d("Download Error", e.toString());
}
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
retrievePosts();
}
});
mSwipeRefreshLayout.setColorSchemeResources(R.color.accentColor, R.color.backgroundColor);
return view;
}
public void retrievePosts()
{
// showing refresh animation before making http call
mSwipeRefreshLayout.setRefreshing(true);
//shared preferences = empty
sharedPreferences.edit().putString("last_time_downloaded", "empty").commit();
try {
ArrayList<ListTypeItem> listItems = new DownloadPosts(getActivity(), mSwipeRefreshLayout).execute().get();
hotListAdapter.updateList(listItems);
hotListAdapter.notifyDataSetChanged();
} catch (Exception e) {
Log.d("Download Error", e.toString());
}
mSwipeRefreshLayout.setRefreshing(false);
//for testing purposes
// new Handler().postDelayed(new Runnable() {
// #Override public void run() {
// mSwipeRefreshLayout.setRefreshing(false);
// }
// }, 5000);
}
}
DownloadPosts.java:
public class DownloadPosts extends AsyncTask<Void, Void, ArrayList<ListTypeItem>> {
SharedPreferences sharedPreferences;
SwipeRefreshLayout swipeRefreshLayout;
public DownloadPosts(Activity activity)
{
this.sharedPreferences = activity.getPreferences(Context.MODE_PRIVATE);
}
public DownloadPosts(Activity activity, SwipeRefreshLayout swipeRefreshLayout)
{
this.sharedPreferences = activity.getPreferences(Context.MODE_PRIVATE);
this.swipeRefreshLayout = swipeRefreshLayout;
}
#Override
protected ArrayList<ListTypeItem> doInBackground(Void... args)
{
StringBuilder parsedString = new StringBuilder();
ArrayList<ListTypeItem> downloadList = new ArrayList<>();
StringBuilder str = new StringBuilder();
if(sharedPreferences.getBoolean("Thomas More",false))
{
str.append("190155257998823,");
}
String school_url = str.toString();
if(school_url.length() > 0)
{
school_url = school_url.substring(0, str.length()-1);
}
try{
String date = "";
//checken of opnieuw moet bepaald worden
// + in de adapter moet als gereload wordt last_time_downloaded == empty
if(!sharedPreferences.getString("last_time_downloaded","empty").equals("empty"))
{
String last_date = sharedPreferences.getString("last_time_downloaded","nothing");
last_date = last_date.replace(" ","T");
date= "&datum_last_posted=" + last_date;
}
URL url = new URL("http://localhost/getpostlist.php?school_post=" + school_url + date);
URLConnection conn = url.openConnection();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String json;
while((json = bufferedReader.readLine())!= null)
{
parsedString.append(json + "/n");
}
String s = parsedString.toString().trim();
//converten van string opgehaald via http naar jsonobject
JSONArray array = new JSONArray(s);
for(int i = 0; i < array.length(); i++)
{
JSONObject tempObj = array.getJSONObject(i);
School_WithoutImage tempSchool = new School_WithoutImage(tempObj.getString("school_id"),
tempObj.getString("post_message"),tempObj.getInt("views"),tempObj.getInt("likes")
,tempObj.getInt("post_id"),tempObj.getString("datum_posted"));
downloadList.add(tempSchool);
if(i == array.length()-1) {
sharedPreferences.edit().putString("last_time_downloaded",tempObj.getString("datum_posted")).commit();
}
}
JSONObject obj = array.getJSONObject(0);
}catch(Exception e)
{
Log.d("Exception", e.toString());
}
return downloadList;
}
#Override
protected void onPostExecute(ArrayList<ListTypeItem> result)
{
if(this.swipeRefreshLayout != null)
{
// swipeRefreshLayout.setRefreshing(false);
}
}
}
I have no idea why the swiperefreshview doesn't spin. Anyone has an idea?
Because the call to get():
.execute().get()
Forces the UI thread to wait for the AsyncTask to finish.
Instead you should look at doing this in the onPostExecute method:
protected void onPostExecute(ArrayList<ListTypeItem> listItems) {
hotListAdapter.updateList(listItems);
hotListAdapter.notifyDataSetChanged();
}
Because you are waiting for the result from asynctask by calling get just after execute. And further passing it to list.
You can use Local Broadcast Listener or can create an interface and can us that as callback, without freezing UI

How to hard-code the url for JSON Parsing?

I would like to hard-code the url for JSON Parsing. Below here is my code:
I changed SERVER_API_URL to TEST_API_URL but it's not working.So, How to i put the hard-code url.
My JSON Parsing coding is different from other online JSON Parsing. Please help me take a look. Thanks.
private class LoadViewTask extends AsyncTask<Void, Integer, Void> {
//Before running code in the separate thread
#Override
protected void onPreExecute() {
//Create a new progress dialog
progressDialog = ProgressDialog.show(getActivity(), "Loading...",
"Loading exam timetable, please wait...", false, false);
}
//The code to be executed in a background thread.
#Override
protected Void doInBackground(Void... params) {
Context ctx = getActivity();
SharedPreferences prefs = ctx.getSharedPreferences(Constants.PREF_NAME, 0);
try {
// res1 = HttpClient.getData(ctx, Constants.SERVER_API_URL + "/timetable/semester/" + prefs.getString("Username", ""));
res1 = HttpClient.getCode(ctx, Constants.TEST_API_URL + "/timetable/semester/" + prefs.getString("Username", "")); //Testing using with my own Url but not working
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
//after executing the code in the thread
#Override
protected void onPostExecute(Void result) {
//close the progress dialog
progressDialog.dismiss();
//initialize the View
if ((res1 != null) && (res1.getHttpCode() == 200)) {
ViewPager pager = (ViewPager) timetable.findViewById(R.id.pager_day);
String res = res1.getBody();
week = new Gson().fromJson(res, WeeklyTimetable.class);
if ((week.getMondayActivities().size() == 0) && (week.getTuesdayActivities().size() == 0) &&
(week.getWednesdayActivities().size() == 0) && (week.getFridayActivities().size() == 0) &&
(week.getThursdayActivities().size() == 0) && (week.getSaturdayActivities().size() == 0) &&
(week.getSundayActivities().size() == 0)) {
RelativeLayout rl = (RelativeLayout) timetable.findViewById(R.id.semesterDay);
rl.removeAllViews();
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
rl.addView(View.inflate(timetable.getContext(), R.layout.fragment_layout_timetable_fail, null), params);
} else {
Calendar calendar = Calendar.getInstance();
int day = calendar.get(Calendar.DAY_OF_WEEK);
pager.setAdapter(buildAdapter(res));
if (day == 1) {
int finalDay = 6;
pager.setCurrentItem(finalDay);
} else {
int finalDay = day - 2;
pager.setCurrentItem(finalDay);
}
pager.setOffscreenPageLimit(7);
}
} else {
RelativeLayout rl = (RelativeLayout) timetable.findViewById(R.id.semesterDay);
rl.removeAllViews();
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
rl.addView(View.inflate(timetable.getContext(), R.layout.fragment_layout_fail, null), params);
TextView text = (TextView) timetable.findViewById(R.id.unavailable);
String str = res1.getBody();
int index = str.indexOf("\"}");
text.setText(str.substring(12, index));
}
}
}
Below here is the class for Constants.SERVER_API_URL and Constants.TEST_API_URL
public class Constants {
/* Hosting Setting */
/* Production */
public static final String SERVER_HOST = "Androidmobile.app.com"; //example
public static final String SERVER_API_URL = "https://Androidmobile.app.com/mobile/api";
public static final String SERVER_API_URL_HTTPS = "https://Androidmobile.app.com/mobile/api";
//Testing Dummy Data
public static final String TEST_API_URL = "http://kyawmyohtet.my3gb.com/ExamTimetable.php";
//End Testing
}
Create a constructor in your Asynctask class,
String url = null;
LoadViewTask (String url){
this.url = url;
}
in your onCreate method or wherever you are creating the instance of AsyncTask,
LoadViewTask task1 = new LoadViewTask("Your URL");
you can then use variable url anywhere in your AsyncTask class to access your url.
Below code change in your
private class LoadViewTask extends AsyncTask<Void, Integer, Void> {
to
private class LoadViewTask extends AsyncTask<String, Integer, Void> {
and in doInBackground() method
protected Void doInBackground(String... params)
{
Context ctx = getActivity();
try {
res1 = HttpClient.getCode(ctx, params[0]);
//Testing using with my own Url but not working
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
and call LoadViewTask like below with hardcode url.
SharedPreferences prefs = this.getSharedPreferences(Constants.PREF_NAME, 0);
String str_URL = Constants.TEST_API_URL + "/timetable/semester/" + prefs.getString("Username", "");
new LoadViewTask().execute(str_URL);
this is hardcode URL passed in your LoadViewTask class when and where you call for response.

Categories