When I run my app, onPostExecute doesn't seem to be called. It is not populated the UI like it should be. Also, on DoInBackground, any log messages past the for loop:
for (int i = 0; i < businesses.length(); i++) { }
excluding the log messages in that particular for loop are not shown. So for example, the log message in the 2nd for loop for(int j = 0; j < businessNames.size(); j++) { } are not shown for some reason. Is this a timing issue or am I missing something?
But just to sum up, the UI in my onPostExecute is not being hit (as I know of).
Here is my code
public class CoffeeResultActivity extends Activity{
ExpandableListAdapter listAdapter;
ExpandableListView expListView;
List<String> businessNames = new ArrayList<String>();
List<String> businessInfo = new ArrayList<String>();
HashMap<String, List<String>> listDataChild = new HashMap<String, List<String>>();
private int lastExpandedPosition = -1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
expListView = (ExpandableListView) findViewById(R.id.lvExp);
//Calling AsyncTask
new RetreiveSearchResults().execute("coffee");
// Listview Group click listener
expListView.setOnGroupClickListener(new OnGroupClickListener() {
#Override
public boolean onGroupClick(ExpandableListView parent, View v,
int groupPosition, long id) {
return false;
}
});
expListView.setOnGroupExpandListener(new OnGroupExpandListener() {
#Override
public void onGroupExpand(int groupPosition) {
if (lastExpandedPosition != -1 && groupPosition != lastExpandedPosition) {
expListView.collapseGroup(lastExpandedPosition);
}
lastExpandedPosition = groupPosition;
}
});
// Listview Group collasped listener
expListView.setOnGroupCollapseListener(new OnGroupCollapseListener() {
#Override
public void onGroupCollapse(int groupPosition) {
Toast.makeText(getApplicationContext(),
businessNames.get(groupPosition) + " Collapsed",
Toast.LENGTH_SHORT).show();
}
});
// Listview on child click listener
expListView.setOnChildClickListener(new OnChildClickListener() {
#Override
public boolean onChildClick(ExpandableListView parent, View v,
int groupPosition, int childPosition, long id) {
// TODO Auto-generated method stub
Toast.makeText(
getApplicationContext(),
businessNames.get(groupPosition)
+ " : "
+ listDataChild.get(
businessNames.get(groupPosition)).get(
childPosition), Toast.LENGTH_SHORT)
.show();
return false;
}
});
}
class RetreiveSearchResults extends AsyncTask<String, Void, Void> {
#Override
protected Void doInBackground(String... terms) {
// Some example values to pass into the Yelp search service.
String category = "coffee";
// Execute a signed call to the Yelp service.
OAuthService service = new ServiceBuilder().provider(YelpApi2.class).apiKey("key").apiSecret("key").build();
Token accessToken = new Token("key", "key");
OAuthRequest request = new OAuthRequest(Verb.GET, "http://api.yelp.com/v2/search");
request.addQuerystringParameter("location", "Waterfront, Boston, MA");
request.addQuerystringParameter("category", category);
service.signRequest(accessToken, request);
Response response = request.send();
String rawData = response.getBody();
try {
JSONObject json = new JSONObject(rawData);
JSONArray businesses;
businesses = json.getJSONArray("businesses");
for (int i = 0; i < businesses.length(); i++) {
JSONObject business = businesses.getJSONObject(i);
//Log.d("FOO FOO", "FOO FOO FOO" + business.toString());
businessNames.add(business.get("name").toString());
//The following log message gets displayed
Log.d("FOO FOO", "FOO FOO " + businessNames.get(i));
businessInfo.add(business.get("rating").toString());
//The following log message gets displayed
Log.d("FOO FOO", "FOO FOO " + businessInfo.get(i));
}
//The following log message gets displayed
Log.d("FOO FOO", "SIZE" + businessNames.size());
for(int j = 0; j < businessNames.size(); j++) {
//The following log message DOES NOT GET DISPLAYED. But it does run through this for loop in debugger.
Log.d("FOO FOO", "FOO FOO ##### Get Here?);
//In Debugger, listDataChild does get populated.
listDataChild.put(businessNames.get(j), businessInfo);
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
protected void onPostExecute() {
//Does not enter onPostExecute in Debugger nor on a Regular run.
//Log message does NOT get printed
Log.d("FOO FOO", "FOO FOO Get in POST?");
listAdapter = new ExpandableListAdapter(CoffeeResultActivity.this, businessNames, listDataChild);
listAdapter.notifyDataSetChanged();
// setting list adapter
expListView.setAdapter(listAdapter);
}
}
}
The signature of onPostExecute is wrong. It should be like
protected void onPostExecute(Void result) {
}
Your onPostExecute does not match the AsyncTasks signature.
Try adding a Void parameter to the method like so:
protected void onPostExecute(Void result){}
You seem to have forgot to add your #Override tag to your onPostExecute
Related
I have succeeded in making more data download and then put it inside Recycleview and I succeeded in doing that and I used everything well but the problem is that I try to load some elements if they contain a value of 3, for example inside the function Loadmore I tried to make a loop and then I put the value 3 and then delete all the value equal to this number
but I have not succeeded so far please help and put the appropriate code
// my code
public class Page_6Fragment extends android.support.v4.app.Fragment implements AdapterView.OnItemSelectedListener {
TextView th, tm, tt, tapm;
Spinner spin_h, spin_m, spin_apm, spin_day;
RadioButton radioReject,radioAccipt ;
RadioGroup radioGroup;
Button buttonDialogReject,buttonDialogAccipt;
Dialog dialog;
RecyclerView recyclerView;
List<Customer> customers;
CustomerAdapter adapter;
View rootView;
String TAG = "MainActivity - ";
Context context;
API api;
Boolean acceptOrNo = true;
Context c = null;
String lock;
public int[] userLock;
public static Page_6Fragment instance;
public static Page_6Fragment newInstance() {
Page_6Fragment fragment = new Page_6Fragment();
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.activity_customer, container, false);
this.context = getActivity();
this.instance = this;
recyclerView = (RecyclerView) rootView.findViewById(R.id.recycler_view);
customers = new ArrayList<>();
// Postion is index item inside recycleview =
adapter = new CustomerAdapter(Page_6Fragment.this,customers){
#Override
public void buttonClickEvent(int position){
// Toast.makeText(context,"posIs: "+position+" userLock.len= "+userLock.length,Toast.LENGTH_SHORT).show();
//showDialog(context,customers.get(position).user_id , Integer.parseInt(customers.get(position).id));
//---- condithion 1
if(customers.get(position).status ==0){
showDialog(context,customers.get(position).user_id , Integer.parseInt(customers.get(position).id));
}else{
Toast.makeText(context,"تم الرد على هذا المستخدم مسبقا", Toast.LENGTH_SHORT).show();
}
}
};
adapter.setLoadMoreListener(new CustomerAdapter.OnLoadMoreListener() {
#Override
public void onLoadMore() {
recyclerView.post(new Runnable() {
#Override
public void run() {
int index = customers.size();
loadMore(index);
}
});
//Calling loadMore function in Runnable to fix the
// java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling error
}
});
recyclerView.setHasFixedSize(true);
// recyclerView.addItemDecoration(new VerticalLineDecorator(2));
recyclerView.setLayoutManager(new LinearLayoutManager(context));
recyclerView.setAdapter(adapter);
api = ServiceGenerator.createService(API.class);
load(0);
return rootView;
}
// load data first time
private void load(int index) {
Call<List<Customer>> call = api.getCustomer(index);
call.enqueue(new Callback<List<Customer>>() {
#Override
public void onResponse(Call<List<Customer>> call, final Response<List<Customer>> response) {
// Toast.makeText(MainActivity.this, "tost "+response.body().get(0).post_writer, Toast.LENGTH_LONG).show();
//Log.i("TRUE_TRUE_","Yes "+response.body().get(2).name);
if (response.isSuccessful()) {
//Log.i("TRUE_TRUE3","Yes"+response.body().toString());
//movies.addAll(response.body());
//adapter.notifyDataChanged();
getActivity().runOnUiThread(new Runnable(){
public void run() {
// No.1 ..............
// ShowDataScreen();
// Toast.makeText( MainActivity.this, "ShowDataScreen",Toast.LENGTH_SHORT).show();
//if(customers.get()){
customers.addAll(response.body());
adapter.notifyDataChanged();
initiUserlock(customers.size());
}
});// end of No.1 UI new thread
getActivity().runOnUiThread(new Runnable() {
public void run() {//No.2
// Toast.makeText( MainActivity.this, "This is correct way",Toast.LENGTH_SHORT).show();
}
});// end of No.2 UI new thread
// Toast.makeText(MainActivity.this, "tost "+response.body().get(0).post_writer, Toast.LENGTH_LONG).show();
} else {
Log.e(TAG, " Response Error " + String.valueOf(response.code()));
}
}
#Override
public void onFailure(Call<List<Customer>> call, Throwable t) {
Log.e(TAG, " Response Error " + t.getMessage());
}
});
}
// laod more data ...................................
private void loadMore(int index) {
// add loading progress view ....
//Toast.makeText(context, "loadMore", Toast.LENGTH_LONG).show();
customers.add(new Customer("load"));
// customers.get(index).user_id =2;
adapter.notifyItemInserted(customers.size() - 1);
Call<List<Customer>> call = api.getCustomer(index);
call.enqueue(new Callback<List<Customer>>() {
#Override
public void onResponse(Call<List<Customer>> call, Response<List<Customer>> response) {
if (response.isSuccessful()) {
//Toast.makeText(context, "it is Successful", Toast.LENGTH_LONG).show();
customers.remove(customers.size() - 1);
List<Customer> result = response.body();
// Log.i("Getresult{--: ", " "+result.get());
if(result.size()>0) {
customers.addAll(result);
//add loaded data
// How to delete every item = 3 from customers list
for (int i=0; i<customers.size(); i++) {
if(customers.get(i).user_id == 3){
// customers.remove(i);
}
}
} else {
//result size 0 means there is no more data available at server
adapter.setMoreDataAvailable(false);
//telling adapter to stop calling load more as no more server data available
Toast.makeText(context,"لايوجد بيانات اخرى", Toast.LENGTH_LONG).show();
}
adapter.notifyDataChanged();
//should call the custom method adapter.notifyDataChanged here to get the correct loading status
} else {
Log.e(TAG, " Load More Response Error000 " + String.valueOf(response.code()));
}
}
#Override
public void onFailure(Call<List<Customer>> call,Throwable t) {
Log.e(TAG, " Load More Response Error_11 " + t.getMessage());
}
});
}
As you already have the new list in the result list, you can solve it by using the result List and add it to the customers List
customers.clear();
for(Customer newCustomer: result){
if(newCustomer.user_id != 3){
customers.add(newCustomer);
}
}
Second option would be to iterate over the customers list using ListIterator
ListIterator<Customer> iter = customers.listIterator();
while(iter.hasNext()){
if(iter.next().user_id == 3){
iter.remove();
}
}
Or
customers.removeIf(customer -> customer.user_id == 3);
I am developing an app, wherein I get JSON data and I am displaying it in the recylcer view. Now on click to the recycler view, on the basis of the item clicked I need to fetch the JSON data from the server and display it in the same recycler view. Its kind of recursive function. I am unable to find anything.
In the MainActivity, I have created an inner class for doing network task
new LauncherLoadThread(rootView).execute(appUsername, appPassword, loadURL, path);
class LauncherLoadThread extends AsyncTask<String, Integer, String[]> {
private View rootView;
public LauncherLoadThread(View rootView) {
this.rootView = rootView;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
progressBar.setVisibility(View.VISIBLE);
}
#Override
protected void onPostExecute(String[] strings) {
super.onPostExecute(strings);
progressBar.setVisibility(View.GONE);
if (strings != null) {
if (strings[0].contentEquals("200")) {
try {
String data = strings[1];
Log.d("Data", data);
JSONArray allData = new JSONArray(data);
for (int i = 0; i < allData.length(); i++) {
JSONObject jsonObject = allData.getJSONObject(i);
String id = jsonObject.getString("id");
String name = jsonObject.getString("name");
String path = jsonObject.getString("path");
String leaf = jsonObject.getString("leaf");
Log.d("Loaded Data: ", "Id: " + id + ". name: " + name + ". Path: " + path);
LauncherModel launcherModel=new LauncherModel(id,name,leaf,path);
launcherModelList.add(launcherModel);
}
adapter=new LauncherAdapter(launcherModelList,getContext());
launcherRecyclerView.setAdapter(adapter);
} catch (JSONException e) {
e.printStackTrace();
}
} else {
Snackbar snackbar = Snackbar.make(rootView, strings[0] + " Something broke down.", Snackbar.LENGTH_LONG);
View snackBarView = snackbar.getView();
TextView tv = (TextView) snackBarView.findViewById(android.support.design.R.id.snackbar_text);
snackbar.show();
}
} else {
Snackbar snackbar = Snackbar.make(rootView, "Oops something went wrong.", Snackbar.LENGTH_LONG);
View snackBarView = snackbar.getView();
TextView tv = (TextView) snackBarView.findViewById(android.support.design.R.id.snackbar_text);
snackbar.show();
}
}
#Override
protected String[] doInBackground(String... strings) {
String username = strings[0];
String password = strings[1];
String url = strings[2];
String path=strings[3];
String processURL="";
if(path.equals("")) {
processURL=url+"?path=Library";
}else {
processURL=url+"?path=" + path;
}
Log.d("doInBackURL", url);
String credential = Credentials.basic(username, password);
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.get()
.addHeader("authorization", credential)
.addHeader("content-type", "application/json")
.build();
try {
Response response = client.newCall(request).execute();
if (response.isSuccessful()) {
String body = response.body().string();
Log.d("Body--->",body);
String code = response.code() + "";
Log.d("Code--->",code);
String[] output = {code, body};
return output;
} else {
String body = "Error: 404";
String code = response.code() + "";
String[] output = {code, body};
return output;
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
Here is my adapter onClickMethod:
public void onBindViewHolder(LauncherViewHolder holder, int position) {
LauncherModel launcherModel = listItem.get(position);
.......
.......
.......
.......
.......
.......
holder.launcherItemRelativeLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
}
});
}
Here you have many options depending on architecture you using. Basically, you can create interface like MyCustomItemClickListener:
interface MyCustomItemClickListener {
void onClick();
}
Than you extend MyCustomItemClickListener by Activity related to RecyclerView and override its method:
#Override
public void onClick(){
// basically, here goes the logic you want on click
}
As I assume you already have ViewHolder in Adapter, the simple option would be to pass Activity as custom Listener in your `Adapter. Than, if we choose this option, it should work like this:
//adapter's inner
class SomeClassViewHolder(val view: View) extends RecyclerView.ViewHolder(view) {
//here can be view initializing, like
txtHeader = (TextView) view.findViewById(R.id.audio_subtitle);
void bind(int position){
// all view binding logic goes here, for example:
txtHeader.setText("someText");
// AND here is also your listener working:
view.setOnClickListener{
listener.onItemClick(item)
}
}
}
//and then in adapter
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
holder.bind(values.get(position));
}
The only trick here is to pass the view(Activity or Fragment) as listener to custom Adapter and it should work.
Edit: For sure, with this approach you can simply reload data from activity with your own logic, like make another async request.
You can simply call notifyDataSetChanged() function of Adapter class.
as i said in the title, i can't figure out how to get the populated array list from makePageRequest method, which uses an inner class
Using Facebook SDK forces me to use certain methods that doesn't allow me to get an arraylist values from method into a global field.
Here is my code from the ListFragment class
public class SelectionFragment extends ListFragment {
private static final String TAG = "SelectionFragment";
public static final String PAGE_URL = "1438734076389483/feed";
private static final int REAUTH_ACTIVITY_CODE = 100;
private static final String[] FROM = { "message", "crated_time", "likes" };
private static final int[] TO = { R.id.feed_box, R.id.created_time, R.id.like_count };
ArrayList<HashMap<String, String>> feedsList;
#Override
public void onAttach(Activity activity) {
Log.d(TAG, "onAttach method is called");
feedsList = new ArrayList<HashMap<String,String>>();
super.onAttach(activity);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d(TAG, "onCreateView method is called");
//super.onCreateView(inflater, container, savedInstanceState);
// Check for an open session
final Session session = Session.getActiveSession();
if (session != null && session.isOpened()) {
// Get the page's feed
makePageRequest(session);
Log.d(TAG, "makePageRequest method is called from onCreateView");
}
SimpleAdapter adapter = new SimpleAdapter(getActivity()
.getBaseContext(), feedsList, R.layout.row, FROM, TO);
setListAdapter(adapter);
return super.onCreateView(inflater, container, savedInstanceState);
}
#Override
public void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "onCreate method is called");
super.onCreate(savedInstanceState);
uiHelper = new UiLifecycleHelper(getActivity(), callback);
uiHelper.onCreate(savedInstanceState);
}
private void makePageRequest(final Session session) {
Log.d(TAG, "makePageRequest method is called");
// Make an API call to get the page feed
// and define a new callback to handle the response.
new Request(session, PAGE_URL, null, HttpMethod.GET, new Request.Callback() {
public void onCompleted(Response response) {
if (session == Session.getActiveSession()) {
if (response != null) {
jSONToArrayList(response);
}
}
if (response.getError() != null) {
// Handle errors
}
}
}).executeAsync();
}
public ArrayList<HashMap<String, String>> jSONToArrayList(
Response facebookJSON) {
Log.d(TAG, "jSONToArrayList method is called");
ArrayList<HashMap<String, String>> dataList = new ArrayList<HashMap<String, String>>();
JSONObject jSONGraphAPI;
JSONArray dataJSONArray;
int likeCount = 0;
String message = "", createdTime = "";
try {
jSONGraphAPI = facebookJSON.getGraphObject().getInnerJSONObject();
dataJSONArray = jSONGraphAPI.getJSONArray("data");
for (int i = 0; i < dataJSONArray.length(); i++) {
JSONObject feedItem = dataJSONArray.getJSONObject(i);
if (feedItem.has("created_time") && feedItem.has("message")) {
message = feedItem.getString("message");
createdTime = feedItem.getString("created_time");
if (feedItem.has("likes")) {
JSONObject likes = feedItem.getJSONObject("likes");
likeCount = likes.length();
}
// Adding value HashMap key => value
HashMap<String, String> map = new HashMap<String, String>();
map.put("message", message);
map.put("crated_time", createdTime);
map.put("likes", String.valueOf(likeCount));
dataList.add(map);
}
// Reset the values to put another data on the HashMap
likeCount = 0;
message = "";
createdTime = "";
}
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
feedsList = (ArrayList<HashMap<String, String>>) dataList.clone();
Log.i("feedsList from jSONToArrayList method: ", feedsList.toString());
return dataList;
}
}
The list that I want to get is feedsList to use it in my adapter. But everytime I run the code the list is empty in onCreateView method, but it's full in makePageRequest and jSONToArrayList method.
Here is a look at my logcat:
D/SelectionFragment(32558): onAttach method is called
D/SelectionFragment(32558): onCreate method is called
D/SelectionFragment(32558): onCreateView method is called
07-23 18:08:17.991: D/OpenGLRenderer(32558): Enabling debug mode 0
07-23 18:08:18.001: D/SelectionFragment(32558): makePageRequest method is called
07-23 18:08:19.221: D/SelectionFragment(32558): jSONToArrayList method is called
07-23 18:08:19.221: I/feedsList from jSONToArrayList method:(32558): [{crated_time=2014-07-23T17:53:22+0000, message=test 123, likes=2}, {crated_time=2014-07-14T10:05:09+0000, message=hello, likes=0}]
In your makePageRequest method you are making an asynchronous web service call. The callback that invokes jSONToArrayList(...) is only invoked when the HTTP call is complete.
But your code, in the onCreateView method, goes on, while another thread is making the HTTP request. So your code immediately passed the feedsList to the SimpleAdapter constructor while the list is still empty.
You should either recreate the SimpleAdapter after you re-assign the feedsList field, or you should not re-assign it (since you have already passed a reference to SimpleAdapter, in that case you need to keep using this reference.). Instead, you can call clear and addAll and make sure that the SimpleAdapter is properly notified of the change in the list contents.
I need some help to fix this problem. I have a PieChart which is drawn in my android App using some data from a MySQL db. I am using an AsyncTask class implementation which loads the data from the server making an HTTPPostRequest and parsing the JSON response that is returned. The chart comes out fine and is drawn on the screen. The problem comes out when I rotate the device's screen: the Chart behaves abnormally and draws slices again... I don't know why it is doing that, but I read that if you rotate the screen all the methods of the Activity are called again (the onCreate(), onStart() and onResume() methods). Maybe it's because of that??? But I am not sure... Here is how is look like:
Then when I rotate the device:
The data are duplicated! Why? What am I mistaking?
Here is all the code:
public class ComeHaInvestito extends Activity {
/**** PieChartBuilder ****/
/** Colors to be used for the pie slices. */
private static int[] COLORS = new int[] { Color.GREEN, Color.BLUE, Color.MAGENTA, Color.CYAN };
/** The main series that will include all the data. */
private CategorySeries mSeries = new CategorySeries("");
/** The main renderer for the main dataset. */
private DefaultRenderer mRenderer = new DefaultRenderer();
/** Edit text field for entering the slice value. */
//private EditText mValue;
/** The chart view that displays the data. */
private GraphicalView mChartView;
private int HowmanyTimes;
#Override
protected void onRestoreInstanceState(Bundle savedState) {
super.onRestoreInstanceState(savedState);
mSeries = (CategorySeries) savedState.getSerializable("current_series");
mRenderer = (DefaultRenderer) savedState.getSerializable("current_renderer");
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putSerializable("current_series", mSeries);
outState.putSerializable("current_renderer", mRenderer);
}
/**** ComeHaInvestito ****/
// String which will store the values of the user
String municipalityName;
String year;
String versedMoney;
// List<Item> ArrayList that will be used to store data from DB
List<Item> MasterAndDetailstatisticsInfoList;
private static final String TAG_COMUNE = "mun_name";
private static final String TAG_ANNO = "year";
private static final String TAG_VERSED_MONEY = "versed_money";
private static final String TAG_SUCCESS = "success";
// POST request information
private static final String URL_ANDROID_APP_LISTENER = "http://xxx.xxx.xxx.xxx/androidApp/AndroidListener.php";
private ProgressDialog pDialog;
// JSONParser instance
JSONParser jParser = new JSONParser();
// JSON data retrieving information
private static final String JSON_STATISTICS_INFOS_LABEL = "statistics_infos";
private static final String JSON_MASTER_LABEL = "master";
private static final String JSON_DETAIL_LABEL = "detail";
private static final String JSON_MASTER_DETAIL_NAME_LABEL = "name";
private static final String JSON_MASTER_DETAIL_VALUE_LABEL ="value";
// statistics info JSON Array which will contain the Master and Detail data that will come from the POST request
JSONArray statisticsInfo = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_come_ha_investito);
Log.d("OnCREATE", "CREO L'ACTIVITY");
// recovering data from previous actitity
Intent iMieiDati = getIntent();
this.municipalityName = iMieiDati.getStringExtra(TAG_COMUNE);
this.year = iMieiDati.getStringExtra(TAG_ANNO);
this.versedMoney = iMieiDati.getStringExtra(TAG_VERSED_MONEY);
// instantiating the needed data structure
MasterAndDetailstatisticsInfoList = new ArrayList<Item>();
mRenderer.setStartAngle(270);
mRenderer.setDisplayValues(true);
new LoadAllMunicipalitiesInvestmentStatisticsThread().execute();
//mRenderer.setZoomButtonsVisible(true);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.pie_chart_builder2, menu);
return true;
}
#Override
protected void onResume() {
super.onResume();
if (mChartView == null) {
LinearLayout layout = (LinearLayout) findViewById(R.id.chart);
mChartView = ChartFactory.getPieChartView(this, mSeries, mRenderer);
mRenderer.setClickEnabled(true);
mChartView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
SeriesSelection seriesSelection = mChartView.getCurrentSeriesAndPoint();
if (seriesSelection == null) {
Toast.makeText(ComeHaInvestito.this, "No chart element selected", Toast.LENGTH_SHORT).show();
}
else {
for (int i = 0; i < mSeries.getItemCount(); i++) {
mRenderer.getSeriesRendererAt(i).setHighlighted(i == seriesSelection.getPointIndex());
}
// mChartView.repaint();
Toast.makeText(
ComeHaInvestito.this,
"Chart data point index " + seriesSelection.getPointIndex() + " selected"
+ " point value=" + seriesSelection.getValue(), Toast.LENGTH_SHORT).show();
}
}
});
layout.addView(mChartView, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
}
else {
//mChartView.repaint();
}
}
private void initChart() {
int i=0;
double value=0;
for (Item item : MasterAndDetailstatisticsInfoList) {
if (i == 4) {
break;
}
Log.d("Ciclo ", "NUMERO " + i);
if (item.getViewType() == EntryType.MASTER.ordinal()) {
MasterWithValue master = (MasterWithValue) item;
Log.d("MASTER NAME", master.getMasterName());
Log.d("MASTER VALUE", master.getMasterValue());
try {
value = Double.parseDouble(master.getMasterValue());
}
catch (NumberFormatException e) {
// value is not a decimal
}
mSeries.add(master.getMasterName(), value);
SimpleSeriesRenderer renderer = new SimpleSeriesRenderer();
renderer.setColor(COLORS[i%4]);
i++;
mRenderer.addSeriesRenderer(renderer);
Log.d("mSeries", mSeries.toString());
}
}
}
/**** Background Thread ****/
public class LoadAllMunicipalitiesInvestmentStatisticsThread extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(ComeHaInvestito.this);
pDialog.setMessage("Caricamento...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
#Override
protected String doInBackground(String... args) {
Log.d("ilMioComune", "Caricamento Statistiche Investimenti");
// building the HTTP POST request
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair(TAG_COMUNE, municipalityName));
params.add(new BasicNameValuePair(TAG_ANNO, year));
params.add(new BasicNameValuePair(TAG_VERSED_MONEY, versedMoney));
Log.d("params", params.toString());
JSONObject json = jParser.makeHttpRequest(URL_ANDROID_APP_LISTENER, "POST", params);
Log.d("JSON POST statistics investments", json.toString());
try {
int success = json.getInt(TAG_SUCCESS);
if (success == 1) {
statisticsInfo = json.getJSONArray(JSON_STATISTICS_INFOS_LABEL);
// foreach Statistics Master Entry
for (int i = 0; i<statisticsInfo.length(); i++) {
JSONObject JSONstatisticsInfo = statisticsInfo.getJSONObject(i);
JSONObject JSONmasterEntry = JSONstatisticsInfo.getJSONObject(JSON_MASTER_LABEL);
String masterEntryName = JSONmasterEntry.getString(JSON_MASTER_DETAIL_NAME_LABEL);
String masterEntryValue = JSONmasterEntry.getString(JSON_MASTER_DETAIL_VALUE_LABEL);
MasterAndDetailstatisticsInfoList.add(new MasterWithValue(masterEntryName, masterEntryValue));
JSONArray JSONdetails = JSONmasterEntry.getJSONArray(JSON_DETAIL_LABEL);
for (int j = 0; j<JSONdetails.length(); j++) {
JSONObject JSONdetailEntry = JSONdetails.getJSONObject(j);
String detailEntryName = JSONdetailEntry.getString(JSON_MASTER_DETAIL_NAME_LABEL);
String detailEntryValue = JSONdetailEntry.getString(JSON_MASTER_DETAIL_VALUE_LABEL);
MasterAndDetailstatisticsInfoList.add(new Detail(detailEntryName, detailEntryValue));
}
}
}
else {
// no statistics infos associated to the selected municipality were found
}
}
catch (JSONException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String file_url) {
pDialog.dismiss();
runOnUiThread(new Runnable() {
#Override
public void run() {
String MasterAndDetails = MasterAndDetailstatisticsInfoList.toString();
Log.d("List", MasterAndDetails);
// Creating the pie chart using the data recovered from the DB
initChart();
}
});
}
}
}
Does anyone have any idea on how to resolve this problem?
Thanks for the attention! Hope fore some help!
You are correct in that onCreate(), onResume(), etc. get called whenever you rotate. Because of this, you are calling new LoadAllMunicipalitiesInvestmentStatisticsThread().execute(); twice essentially.
You should move your data initialization logic to one place, and either load that data from the savedInstanceState, or call the initialize logic if the savedInstanceState returns null.
For example:
change declaration to
private CategorySeries mSeries = null;
in onCreate()
if(savedInstanceState != null)
mSeries = (CategorySeries) savedInstanceState.getSerializable("current_series");
if(mSeries == null)
{
mSeries = new CategorySeries("");
new LoadAllMunicipalitiesInvestmentStatisticsThread().execute(); //this line can be substituted for a new init method, which would contain the thread.execute
}
I am having a problem with getting the result from an asyncTask in a separate class. I have followed from a similar questions answer on here but I cant see where I have gone wrong.
My AsyncTask is in a separate class for easy calling, I needed to be able to have the notice that the asyntask had completed and then start the next activity.
I would welcome any help as I am not sure quite where I have gone wrong.
public class StartScreen extends Activity{
ProgressDialog pd;
CountDownTimer waitTimer;
public static final String APP_PREFERENCES = "AppPrefs";
SharedPreferences settings;
SharedPreferences.Editor prefEditor;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start_screen);
settings = getSharedPreferences(APP_PREFERENCES, MODE_PRIVATE);
// getPreferences();
// prefEditor = settings.edit();
waitTimer = new CountDownTimer(2000, 300) {
public void onTick(long millisUntilFinished) {
//called every 300 milliseconds, which could be used to
//send messages or some other action
}
public void onFinish() {
//After 2000 milliseconds (2 sec) finish current
//if you would like to execute something when time finishes
pd = ProgressDialog.show(StartScreen.this,"Title","Detail text",true,false,null);
getPreferences();
}
}.start();
}
private void getPreferences() {
String UserName = settings.getString("UserName", null);
if (UserName != null) {
// the key does not exist
Intent intent=new Intent(StartScreen.this,InitialPreferences.class);
startActivity(intent);
} else{
//if (UserName.equals(UserName)){
// handle the value
dataTask();
//pd.dismiss();
}
}
private void dataTask() {
// TODO Auto-generated method stub
new DATATask(this).execute(new FragmentCallback(){
#Override
public void onTaskDone() {
startMainAct();
}
});
}
private void startMainAct() {
Intent intent=new Intent(StartScreen.this,MainActivity.class);
startActivity(intent);
}
public interface FragmentCallback {
public void onTaskDone();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.start_screen, menu);
return true;
}
}
AsyncTask:
public class DATATask extends AsyncTask<Void, Void, ArrayList<String>> {
private FragmentCallback mFragmentCallback;
public void execute(FragmentCallback fragmentCallback) {
mFragmentCallback = fragmentCallback;
}
ArrayList<String> arr_data=new ArrayList<String>();
private Context context;
public DATATask(Context context)
{
this.context = context;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected ArrayList<String> doInBackground(Void... params) {
Document docVts, docTide;
String shippingList, tideTimes;
try {
docVts = Jsoup.connect("https://vts.mhpa.co.uk/main_movelistb.asp").timeout(600000).get();
Elements tableRows = docVts.select("table.dynlist td:eq(0),td:eq(1),td:eq(3),td:eq(4),td:eq(7),td:eq(8)");
tableRows.size();
for(int i = 1; i < 80; i++){//only allows x results from vts list, from 1 not 0. 0 produces needless results
shippingList = tableRows.get(i).text().replaceAll(" | ", "") +"\n";
arr_data.add(shippingList);// add value to ArrayList
System.out.println(shippingList);
};
docTide = Jsoup.connect("http://www.mhpa.co.uk/search-tide-times/").timeout(600000).get();
Elements tideTimeOdd = docTide.select("div.tide_row.odd div:eq(0)");
Elements tideTimeEven = docTide.select("div.tide_row.even div:eq(0)");
Elements tideHightOdd = docTide.select("div.tide_row.odd div:eq(2)");
Elements tideHightEven = docTide.select("div.tide_row.even div:eq(2)");
Element firstTideTime = tideTimeOdd.first();
Element secondTideTime = tideTimeEven.first();
Element thirdTideTime = tideTimeOdd.get(1);
Element fourthTideTime = tideTimeEven.get(1);
Element firstTideHight = tideHightOdd.first();
Element secondTideHight = tideHightEven.first();
Element thirdTideHight = tideHightOdd.get(1);
Element fourthTideHight = tideHightEven.get(1);
System.out.println("first tide time: " + firstTideTime.text() + " " + firstTideHight.text());
System.out.println("second tide time: " + secondTideTime.text() + " " + secondTideHight.text() );
System.out.println("third tide time: " + thirdTideTime.text() + " " + thirdTideHight.text());
System.out.println("fourth tide time: " + fourthTideTime.text() + " " + fourthTideHight.text());
{
/*
Work with data - all is OK
*/
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return arr_data;//<< return ArrayList from here
}
#Override
protected void onPostExecute(ArrayList<String> result) {
mFragmentCallback.onTaskDone();
}
}
Thanks for any help.
You are not calling the correct AsyncTask.execute(). The correct execute will invoke the onPreExecute() then doInBackground() then onPostExecute().
new DATATask(this).execute(new FragmentCallback(){
#Override
public void onTaskDone() {
startMainAct();
}
});
}
will call this method (the wrong one):
public void execute(FragmentCallback fragmentCallback) {
mFragmentCallback = fragmentCallback;
}
What you want to do is change this method to - setFragmentCallBack(FragmentCallback);
Then in the OnPostExecute() add this: startMainAct();
instead of doing this:
#Override
public void onTaskDone() {
startMainAct();
}
After this is done, then call the new DATATask(this).execute();
which will invoke the preExecute(), doInbackground, and PostExecute()
What you are doing is adding the FragCallback to the DataTask and not invoking the correct execute function.
I hope this helps.
Actually you did not execute your AsyncTask. You should call "super.execute(Params... params);" in you overloaded execute(FragmentCallback) method.
In your Activity:
DataTask dataTask = new DataTask();
dataTask.execute();
In your AsyncTask class:
onPostExecute(){
//put your intent to start the activity or whatever you want to do when it finishes
}
I think it is much simpler than you are making it. Hope that helps. Also, see AsyncTask Android example
You didn't execute the AsyncTask. Calling DATATask.execute(FragmentCallback) will just assign the callback to your task. You need to call either AsyncTask#execute(Runnable), AsyncTask#execute(Params...) or AsyncTask#executeOnExecutor(Executor exec, Params... params).
Also, I would pass the callback to DATATask via the constructor or a setter, instead of creating a new overloaded execute(FragmentCallback) method. It can easily confuse people.