I'm doing this code for my android programming school project and I've come into a problem which it seems that the JSON has an error in retrieving some of the data from the API it was to take from.
This is an water intake app I'm working on and I'm using the free API provided by openweathermap.org while referencing the code from http://code.tutsplus.com/tutorials/create-a-weather-app-on-android--cms-21587 . The difference is that instead of using a activity and a fragment, I've combined the fragment and activity together with minor modifications to make it runnable on Eclipse.
Here's my code where it goes wrong:
private void updateWeatherInfo(final String city) {
new Thread(){
public void run(){
final JSONObject json = FetchData.getJSON(MainActivity.this, city);
if(json == null) {
handleWeather.post(new Runnable() {
public void run() {
Toast.makeText(MainActivity.this, R.string.place_not_found, Toast.LENGTH_LONG).show();
}
});
}
else {
handleWeather.post(new Runnable() {
public void run() {
renderWeather(json);
}
});
}
}
}.start();
}
private void renderWeather(JSONObject json) {
try {
cityData.setText(json.getString("name").toUpperCase(Locale.US) + ", " + json.getJSONObject("sys").getString("country"));
JSONObject details = json.getJSONArray("weather").getJSONObject(0);
JSONObject main = json.getJSONObject("main");
detailsData.setText(details.getString("description").toUpperCase(Locale.US) + "\n" + "Humidity: " + main.getString("humidity") + "%" + "\n" + "Pressure: " + main.getString("pressure") + " hPa");
currentTemperatureData.setText(String.format("%.2f", main.getDouble("temp"))+ " ℃");
DateFormat df = DateFormat.getDateTimeInstance();
String updatedOn = df.format(new Date(json.getLong("dt")*1000));
updatedData.setText("Last update: " + updatedOn);
getWeatherIcon(details.getInt("id"), json.getJSONObject("sys").getLong("sunrise") * 1000, json.getJSONObject("sys").getLong("sunset") * 1000);
}
catch(Exception e) {
Log.e("SimpleWeather", "One or more fields not found in the JSON data");
}
}
The exception at the try/catch keeps one happening once it reaches cityData and detailsData. I know this because when I debugged it and reaching there it goes straight to the catch after a few step ins, and with commenting out the cityData the next time it got routed to the catch again was at detailsData.
Could anyone see what's wrong and help me point it out?
EDIT: here's the API im using - http://api.openweathermap.org/data/2.5/weather?q=Singapore,sg
EDIT2: It seems it is because my onCreateView which initialises my textViews was after the updateWeatherData and I've since moved it first before the updateWeatherData was called. Now, however, I realise that my onCreateView has also no #Override, and upon putting in the #Override an error occurs that it must implement a supertype method.
The code is as such:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.activity_main, container, false);
cityData = (TextView)rootView.findViewById(R.id.city_field);
updatedData = (TextView)rootView.findViewById(R.id.updated_field);
detailsData = (TextView)rootView.findViewById(R.id.details_field);
currentTemperatureData = (TextView)rootView.findViewById(R.id.current_temperature_field);
weatherIcon = (TextView)rootView.findViewById(R.id.weather_icon);
weatherIcon.setTypeface(weatherIcons);
return rootView;
}
I understand that this code was meant for a fragment, but implementing it into an Activity it seems I have missed a step in modifying it here. How do I proceed from here?
EDIT3: I have now implemented the onCreateView data into the onCreate , since the onCreateView is the fragment version of onCreate . However, I have run into another problem that is out of this question's scope in that my setTypeface returns a NullPointerException. he code of which can be seen below:
public class MainActivity extends Activity {
TextView cityData;
TextView updatedData;
TextView detailsData;
TextView currentTemperatureData;
TextView weatherIcon;
Typeface weatherIcons;
Handler handleWeather;
public MainActivity() {
handleWeather = new Handler();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
cityData = (TextView) findViewById(R.id.city_field);
updatedData = (TextView) findViewById(R.id.updated_field);
detailsData = (TextView) findViewById(R.id.details_field);
currentTemperatureData = (TextView) findViewById(R.id.current_temperature_field);
weatherIcon = (TextView) findViewById(R.id.weather_icon);
weatherIcons = Typeface.createFromAsset(getAssets(), "weather.ttf");
weatherIcon.setTypeface(weatherIcons);
As such, I will continue my search to this problem for a while, and if I find my answer, I will not post up another question. However, I shall close this question as answered.
Related
I have encountered a weird bug in my fragment class: imageViews "disappear" if I rotate/reload the view. From my understanding, rotating/reloading destroys the View and re-creates it, so local variables and local view elements may not preserve. However, I have made a manual button that should manually render the images again after I click it, yet the ImageViews stay gone even if I manually reset their imageResource or imageBackground resource. Note that these imageviews are animated-drawables. Below is most of my code:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_home, container, false);
mView = rootView; //mView is global
return rootView;
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Log.d("gnereed id", "id is "+R.id.generate_button);
final Button generate_button = getView().findViewById(R.id.generate_button);
if ( bottleMap == null ) bottleMap = new Hashtable();
// the code sets all images to invisible onCreate
// their visibility will be changed when a bottle is "created"
ImageView[] bottles = new ImageView[7];
for (int i = 0; i < bottleAry.length; i++){
bottles[i] = getView().findViewById(bottleAry[i]);
bottles[i].setVisibility(View.GONE);
}
// this is a button that generates a new bottle and manually refreshes all previous bottle
// If fragment has not been reloaded/rotated then everything works here
// after fragment reloads, new bottles can be generated but old bottles do not re-render.
generate_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Bottle bottle = new Bottle("123", bottleList.size());
bottle.setVisible();
bottleList.add(bottle);
Log.e(" mView : ", mView.toString());
// for all bottles created, re-render them
for (int i = 0; i < bottleList.size(); i ++) {
bottleList.get(i).reRender();
}
}
});
}
public class Bottle{
String message;
ImageView bottleLocation;
int imageSrc;
int avail_index;
int bottle_index;
int locationID;
AnimationDrawable bottleAnimation;
public Bottle(String msg, int bottle_index){
message = msg;
this.bottle_index = bottle_index;
locationID = getRandomBottleLocation();
bottleLocation = getView().findViewById(locationID);
Log.e(" old View : ", getView().toString());
// sets the image source and sets visible, lastly start animation
imageSrc = getRandomBottleImg();
bottleLocation.setBackgroundResource(imageSrc);
bottleMap.put(Integer.toString(locationID), imageSrc);
bottleAnimation = (AnimationDrawable) bottleLocation.getBackground();
bottleAnimation.start();
bottleLocation.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(getActivity(), ViewBottleActivity.class));
availableLocation[avail_index] = false;
bottleMap.remove(Integer.toString(locationID));
bottleAnimation.stop();
bottleLocation.setVisibility(View.GONE);
bottleList.remove(bottle_index);
}
});
}
public int getRandomBottleImg(){
int bottle;
Random rand = new Random();
bottle = imgAry[rand.nextInt(imgAry.length)];
return bottle;
}
public int getRandomBottleLocation(){
int location;
Random rand = new Random();
avail_index = rand.nextInt(bottleAry.length);
while (availableLocation[avail_index]){
avail_index = rand.nextInt(bottleAry.length);
}
location = bottleAry[avail_index];
availableLocation[avail_index] = true;
return location;
}
public void reRender(){
Log.e("location ID is:" , Integer.toString(this.locationID));
bottleLocation = mView.findViewById(this.locationID);
Log.e("ImageView is:" , bottleLocation.toString());
imageSrc = getRandomBottleImg();
bottleLocation.setBackgroundResource(imageSrc);
bottleAnimation = (AnimationDrawable) bottleLocation.getBackground();
bottleAnimation.stop();
bottleAnimation.start();
this.setVisible();
}
public void setVisible(){
bottleLocation.setVisibility(View.VISIBLE);
}
I fixed the problem. What I learned is that you cannot use
View.findViewByID(viewID)
outside of onViewCreated(). Notice how I implemented reRender() function inside the onViewCreated() but it didn't work? The result is that mView.findViewByID(viewID) is actually executed OUTSIDE OF onViewCreated() although I call the function from WITHIN.
Yes, the line will be executed, but upon inspection, mView.findViewByID(viewID) will return TWO DIFFERENT objects when called from inside onViewCreated() and when called from a function that is called from onViewCreated().
This is very counterintuitive, especially for us who's taught to deploy the DRY(do not repeat urself) principle. The fix is just to simply not write outside functions for handling View.
I have been trying to solve this issue for a while but seems not to work. I am getting a nullPointer Exception on this Line school.setClasses(classesName.getText().toString());in the code block below.
Which is the code that actually posts to the SQLite Database
public void postSchoolSetuptoSQLite() {
school.setSchoolName(nameOfSchool.getText().toString());
school.setSchoolLocation(schoolLocation.getText().toString());
school.setClasses(classesName.getText().toString());
academeaSQL.addSchool(school);
if (demeaSQL != null) {
StringBuilder sb = new StringBuilder();
for (School s : demeaSQL.getAllSchools()) {
sb.append(" SchoolName= " + s.getSchoolName() + " SchoolLocation= " + s.getSchoolLocation()
+ " ClassName= " + s.getClasses());
sb.append("\n");
}
Log.i("Database content", sb.toString());
Toast.makeText(getApplicationContext(), "Added Successfully", Toast.LENGTH_LONG).show();
} else {
Log.i("Database Err", "Database Error");
}
}
I am creating the field for the classesName dynamically by clicking an "Add New Class" Button through this onAddField Method
public void onAddField(View v) {
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
rowView = inflater.inflate(R.layout.field, null);
rowView.setId(ViewIdGenerator.generateViewId());
// Add the new row before the add field button.
parentLinearLayout.addView(rowView, parentLinearLayout.getChildCount() - 1);
Log.i("ids", String.valueOf(rowView.getId()));
}
The field Id is dynamically generated through the ViewIdGenerator Class.
The Error is at this point classesName = rowView.findViewById(rowView.getId()); when getting the Ids from the dynamically created fields in this code block
public void findByIds() {
rowView = new View(this);
parentLinearLayout = findViewById(R.id.parent_linear_layout);
nameOfSchool = findViewById(R.id.nameOfSchool);
schoolLocation = findViewById(R.id.schoolLocation);
addSchoolAndMoveNext = findViewById(R.id.addSchoolAndMoveNext);
classesName = rowView.findViewById(rowView.getId());
Log.i("Classname", String.valueOf(classesName));
Log.i("SchoolLoca", String.valueOf(schoolLocation));
}
Here is where I am calling the findByIds();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_school_search_setup);
findByIds();
intitializeListeners();
initializeObjects();
}
For the Nullpointer exception. the error is pointing at these areas
school.setClasses(classesName.getText().toString());
and
classesName = rowView.findViewById(rowView.getId());
Please why am I getting the nullpointer exception and How can I resolve it. Thank you. I will really appreciate your responses.
Your problem is that if you are calling findByIds() inside of onCreate() then rowView.getId() will return null, because you are setting the id in the default id generator AFTER the button gets pressed. onCreate() gets called when the activity first starts up.
It also looks like you are trying to add a list of classes when you hit the button. There are built in ways to do this in Android that have a bit more overhead than what you are doing (in terms of time it takes to implement) but that are going to be much more reliable for scrolling, adding new classes, deleting classes, etc.
Look into the recyclerview in order to do this
Inside of the Display Cursor contents in a RecyclerView section here will show you how to add data from the database to the RecyclerView
i'm trying to download a list of cases from a server and then populate an arraylist to use it in my RecyclerView Adapter but every time i try to populate the array list from asynctask i can print the data in every single step from the populating bu not from the Arraylist i'm using (i'm trying to store in an arrayList that contains objects of the type Case which i created)
this is the part of the code with the problem
this is my AsyncTask...
`
public class downloadingNewCases extends AsyncTask<Void,Void ,Boolean>{
private String userid ;
private String state ;
public downloadingNewCases(String userid ,String state ){
this.userid = userid ;
this.state = state ;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
Log.d(AppController.DEBUG, "download New Cases Started");
}
#Override
protected Boolean doInBackground(Void... params){
Log.d(AppController.DEBUG , "user id in the get cases link.." + userid);
String url = AppController.ApiUrl + "GetCases?UserName="+ userid +"&stat="+state;
Log.d(AppController.DEBUG_LINK,url);
try {
JsonArrayRequest request = new JsonArrayRequest(url, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.d("TEST", String.valueOf(response.length()));
for (int i = 0; i < response.length(); i++) {
try {
Log.d("TEST","downloading data" );
JSONObject object = response.getJSONObject(i);
JSONArray specs = object.getJSONArray("Spe");
ArrayList<Specialities> spe = new ArrayList<>();
for (int j = 0; j < specs.length(); j++) {
Log.d("TEST",specs.getJSONObject(j).getString("SName") );
spe.add(new Specialities(null, specs.getJSONObject(j).getString("SName")));
}
Case ca = new Case(object.getString("ID")
, object.getString("Serial")
, object.getString("Name")
, object.getString("gender")
, object.getString("Age")
, object.getString("NatioanlityID")
, object.getString("HealthProblem")
, object.getString("CityID")
, object.getString("Problem")
, object.getString("Date")
, object.getString("Status")
, spe);
Log.d("TEST",ca.toString());
cases.add(ca);
spe.clear();
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError volleyError) {
Log.d(AppController.DEBUG , volleyError.toString());
}
});
request.setRetryPolicy(new DefaultRetryPolicy(
0,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
MySingleton.getmInstance(getActivity()).addToRequestQueue(request);
}catch (Exception e){
Log.d(AppController.DEBUG,"error in the asynctask in the new cases freagment... ");
Log.d(AppController.DEBUG ,e.toString());
}
Log.d(AppController.DEBUG, "Cases size ::" + cases.size());
return true;
}
#Override
protected void onPostExecute(Boolean bool) {
super.onPostExecute(bool);
/* if(listener != null){
listener.getCases(cases);
}*/
adapter.notifyDataSetChanged();
// Log.d(AppController.DEBUG, "new Cases Downloaded...");
}
}
`
(I'm sure that the adapter and recycler view code is correct because I could use the same code now but when I came to test it again it did not work anymore and I can't remember if I changed some thing in it or not - I think not)..
this is my onViewCreate Method .
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.doctor_new_cases_fragment,container,false);
Log.d(AppController.DEBUG_SHARED,"userID in the new case activity ..." + userID);
SharedPreferences prefs = getActivity().getSharedPreferences(AppController.PREFERENCES_NAME , Context.MODE_PRIVATE);
userID = prefs.getString(DoctorProfileSubmitActivity.Shared_userid,null) ;
downloadingNewCases tast = new downloadingNewCases(userID ,"");
tast.execute();
recyclerView = (RecyclerView)view.findViewById(R.id.recyclervew_new_cases);
adapter = new CasesAdapter(view.getContext(), cases);
recyclerView.setLayoutManager(new LinearLayoutManager(view.getContext()));
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(adapter);
ViewGroup parent = (ViewGroup) view.getParent();
if (parent != null){
parent.removeView(view);
}
return view;
}
and finally the Array list is declared as an instance variable of the class (the class extends Fragment + it is a fragment that I'm using in my view pager as a tab layout for my tabbed Activity .)
here's the ArrayList declaration
private final ArrayList<Case> cases = new ArrayList<>();
Since you say you can print the data every step of the way, the problem is probably not related to your data. The problem might be your Arraylist of case And your CaseAdapter.
Let's try a simple test, instead of filling your adapter with case objects, create a new ArrayList of string and fill it with object.getString("name") in your on response. Then change your oncreateview to display this list of names using a normal string arrayadapter.
If you can successfully display the names, the it means the bug is in your case and caseadapter, you would have to show more code for us to help.
sorry guys it was not worth it to add a question on the site right away
i fixed the problem . (it appears that my problem was here)
Case ca = new Case(object.getString("ID")
, object.getString("Serial")
, object.getString("Name")
, object.getString("gender")
, object.getString("Age")
, object.getString("NatioanlityID")
, object.getString("HealthProblem")
, object.getString("CityID")
, object.getString("Problem")
, object.getString("Date")
, object.getString("Status")
, spe);
i accidentally changed object.getString("Gender") to object.getString("gender")
which caused me a JSONException .
i fixed that and everything is working again .
thanks for your help and i'm sorry if i rushed to ask the question without a proper debugging session first .
I've searched all the posts I can find, and none seem to help with my situation. I have an android project that uses web services to pull down hourly weather data and populate a listView with the results.
The weird problem I'm having is that when I debug the project on my android phone, the main activity is blank and the listView isn't populated. If I run the project from android studio with my phone locked, and then unlock my phone the app opens on my phone with all of the listView properly formatted and populated.
I feel like it's a race condition issue between the asynctask and the adapter, but I can't seem to resolve it. I tried making my asyncTask an inner private class and calling notifyDataSetChanged on the adapter inside the onPostExecute method, but to no avail. I feel it must be something simple, but I'm relatively new to Android dev, so I'm stuck.
I have three classes that I'll post the pertinent code from
MainActivity.java (onCreate)
public class MainActivity extends ActionBarActivity {
ArrayList<Weather> w = new ArrayList<Weather>();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DownloadWeatherTask myTask = new DownloadWeatherTask(w);
WeatherAdapter myAdapter = new WeatherAdapter(this,w);
ListView l = (ListView) findViewById(R.id.weatherList);
l.setAdapter(myAdapter);
myTask.execute();
}
}
WeatherAdapter.java
public class WeatherAdapter extends ArrayAdapter<Weather>{
public WeatherAdapter(Context context, ArrayList<Weather> weather) {
super(context, R.layout.item_weather, weather);
}
public View getView(int position, View convertView, ViewGroup parent) {
// Get the data item for this position
Weather forecast = getItem(position);
// Check if an existing view is being reused, otherwise inflate the view
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_weather, parent, false);
}
// Lookup view for data population
TextView tvTime = (TextView) convertView.findViewById(R.id.listTime);
TextView tvDescr = (TextView) convertView.findViewById(R.id.listDescr);
TextView tvTemp = (TextView) convertView.findViewById(R.id.listTemp);
TextView tvHumid = (TextView) convertView.findViewById(R.id.listHumid);
ImageView ivWeather = (ImageView) convertView.findViewById(R.id.weatherImg);
// Populate the data into the template view using the data object
tvTime.setText(forecast.time);
tvDescr.setText(forecast.description);
tvTemp.setText(forecast.temperature+"°(F)");
tvHumid.setText(forecast.humidity+"% humidity");
ivWeather.setImageBitmap(forecast.weatherImg);
// Return the completed view to render on screen
return convertView;
}
}
DownloadWeatherTask.java
public class DownloadWeatherTask extends AsyncTask<Void,Void,Void>{
ArrayList<Weather> data;
public DownloadWeatherTask(ArrayList<Weather> a){
data = a;
}
public ArrayList<Weather> getData() {
return data;
}
protected Void doInBackground(Void...params) {
try {
String website = "http://api.wunderground.com/api/1111111111111/geolookup/q/autoip.json";
URL site = new URL(website);
HttpURLConnection weatherUnderground = (HttpURLConnection) site.openConnection();
weatherUnderground.connect();
JsonParser weatherParser = new com.google.gson.JsonParser();
JsonElement weatherJson = weatherParser.parse(new InputStreamReader((InputStream) weatherUnderground.getContent()));
JsonObject weatherObj = weatherJson.getAsJsonObject();
String zip = weatherObj.get("location").getAsJsonObject().get("zip").getAsString();
String city = weatherObj.get("location").getAsJsonObject().get("city").getAsString();
String state = weatherObj.get("location").getAsJsonObject().get("state").getAsString();
String hourly = "http://api.wunderground.com/api/111111111111/hourly/q/" + state + "/" + city + ".json";
URL hourlySite = new URL(hourly);
HttpURLConnection hourlyConnection = (HttpURLConnection) hourlySite.openConnection();
hourlyConnection.connect();
com.google.gson.JsonParser hourlyParser = new com.google.gson.JsonParser();
JsonElement hourlyWeatherJson = weatherParser.parse(new InputStreamReader((InputStream) hourlyConnection.getContent()));
JsonArray weatherArr = hourlyWeatherJson.getAsJsonObject().get("hourly_forecast").getAsJsonArray();
int l = weatherArr.size();
for (int i = 0; i < l; i++) {
String date = weatherArr.get(i).getAsJsonObject().get("FCTTIME").getAsJsonObject().get("pretty").getAsString();
String temp = weatherArr.get(i).getAsJsonObject().get("temp").getAsJsonObject().get("english").getAsString();
String condition = weatherArr.get(i).getAsJsonObject().get("condition").getAsString();
String humidity = weatherArr.get(i).getAsJsonObject().get("humidity").getAsString();
String iconUrl = weatherArr.get(i).getAsJsonObject().get("icon_url").getAsString();
Bitmap icon = getBitmapFromURL(iconUrl);
data.add(new Weather(date, condition, temp, humidity, icon));
}
} catch (IOException e) {
Log.e("Error: ",e.toString());
}
return null;
}
protected void onPostExecute(Void...params){
}
}
Below are links to my screenshots showing the app not populating the listView, and the app working properly when the program is run while the phone is initially locked.
Any help would be greatly appreciated!!
Thanks
In postExecute(), you need to update the adapter's List and then invoke its notifyDataSetChanged method. I suspect that you were forgetting to update the adapter's data.
The other option is to create a new adapter with the new data, and set the new adapter on the ListView.
I figured out what the issue was! I hadn't added #Override to my onPostExecute() method so it was never being called.
I added the notifyDataSetChanged to my onPostExecute as suggested, which worked once I added the #override to my method.
It is always the little things that stump me for hours.
I have an onPostExecute method from an AsyncTask class that looks like so:
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
showColumnCounts();
dataDownloadCompleteToast();
}
The toast works just fine. However, my showColumnCounts() method refuses to work. It works just fine on the main thread. I use it during onCreate() just not here. I thought the onPostExecute ran on the UI thread?
Here is my showColumnCounts() method if it is relevant.
public void showColumnCounts() {
TextView totalView = (TextView) findViewById(R.id.totalColumn2);
TextView ignoredView = (TextView) findViewById(R.id.ignoredColumn2);
TextView rView = (TextView) findViewById(R.id.rColumn2);
Cursor c = myDB.getEmptyRColumn("");
int count = c.getCount();
if (count == 0) {
c.close();
return;
}
String unread = String.valueOf(count);
String total = getTotalCount();
int tTotal = Integer.parseInt(total);
int r = tTotal - count;
String read = String.valueOf(r);
totalView.setText(total);
ignoredView.setText(unread);
rView.setText(read);
c.close();
}
I've been fiddling with it for a while now assuming the answer should be obvious but I'm calling uncle. Can't figure it.
Edit***** 6/30
I THINK I've found my problem. In my background thread I am using a parse.com method "query.findInBackground" which I assume is starting a third thread? I'm trying to update this to "query.find" and I'm hoping that will fix.
First of all you should move all your TextView declarations inside your onCreate method
if you want to change or perform some UI operation, if you want to perform some non UI based operations while the thread is running then do that in doInBackground() method
You should move …setText(...) lines into
runOnUiThread(new Runnable(){
void run(){
// UI stuff
});
You need to tell where is your async class located and the showColumnCounts() function located.
If they both where in different class then you should create a context to call the function from the async class.
Take this as example and try.
Example:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.main);
new AsyncClass(this);
super.onCreate(savedInstanceState);
}
public void showColumnCounts() {
TextView totalView = (TextView) findViewById(R.id.totalColumn2);
TextView ignoredView = (TextView) findViewById(R.id.ignoredColumn2);
TextView rView = (TextView) findViewById(R.id.rColumn2);
Cursor c = myDB.getEmptyRColumn("");
int count = c.getCount();
if (count == 0) {
c.close();
return;
}
String unread = String.valueOf(count);
String total = getTotalCount();
int tTotal = Integer.parseInt(total);
int r = tTotal - count;
String read = String.valueOf(r);
totalView.setText(total);
ignoredView.setText(unread);
rView.setText(read);
c.close();
}
public class AsyncClass extends AsyncTask<String, Void, Boolean> {
private Activity activity;
public AsyncClass(Activity main_activity) {
this.activity = main_activity;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
activity.showColumnCounts();
dataDownloadCompleteToast();
}
}
}
If you want to do some UI change process in background running operation(ASYNC TASK),you write that codes in UI thread. Example:
YourActivity.this.runOnUiThread(
new Runnable()
void run()
{
//UI changes
showColumnCounts();
});