variable returns null outside asynctask android - java

I have an asynctask which gets its data through php. The asynctask works fine, it passes the values to a global arraylist. However, when i try to call the variable on onCreate after .execute(), it returns a null size/value(s). I would like to know why this global variable returns a null when its supposed to have a value. Thanks in advance!
this is the code for asyntask:
private class get_pendingreq extends AsyncTask<String, Integer, String>
{
#Override
protected String doInBackground(String... arg0)
{
InputStream is = null;
String result = "";
try
{
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(url+"pending_requests.php");
List<NameValuePair> parameter = new ArrayList<NameValuePair>();
parameter.add(new BasicNameValuePair("email", globalVariables.accountemail));
httppost.setEntity(new UrlEncodedFormEntity(parameter));
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
is = entity.getContent();
} catch (Exception e)
{
Log.e("log_tag", "Error in http connection " + e.toString());
}
try
{
BufferedReader reader = new BufferedReader(
new InputStreamReader(is, "iso-8859-1"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null)
{
sb.append(line + "\n");
}
is.close();
result = sb.toString();
} catch (Exception e)
{
Log.e("log_tag", "Error converting result " + e.toString());
}
return result;
}
#Override
protected void onPostExecute(String result)
{
super.onPostExecute(result);
try
{
/* JSON parsing starts here */
JSONObject jArray = new JSONObject(result);
/*globalVariables.pendingdate = new ArrayList<String>();*/
JSONArray request = jArray.getJSONArray("request");
for (int i = 0; i < request.length(); i++)
{
JSONObject e = request.getJSONObject(i);
/* puts values to arraylist<String> */
globalVariables.pendingdate.add(e.getString("date"));
}
Log.d("striiing", globalVariables.pendingdate.toString());
} catch (JSONException e)
{
e.printStackTrace();
}
}
}
Main activity:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.calendar);
new get_pendingreq().execute();
System.out.print("alalala" + globalVariables.pendingdate.size());
}//this returns null
Global Variable:
public static ArrayList<String> pendingdate = new ArrayList<String>;

Because AsyncTask not finished. Put System.out.print("finish"); in onPostExcute() and see who is printed first.

The idea behind an AsyncTask is that it runs asynchronously from the main thread, thus on a background thread. That way it doesn't block the execution of any code on the main thread.
Knowing that, the following lines will execute right after each other:
new get_pendingreq().execute();
System.out.print("alalala" + globalVariables.pendingdate.size());
Your get_pendingreq class will not do any actual work until after a small delay, meaning that after calling the first lines in above snippet, nothing has really happened. You've only instructed the platform to start the async task somewhere in the near future.
Now, the globalVariables.pendingdate field you're accessing on the second line will not have any values until the async task finishes its work. That doesn't happen until onPostExecute() is executed. In other words: you're trying to print the values at the wrong moment in time.
Simply move that print to the end of the async task's onPostExectute() method (but obviously before the return - why's that even there at all?).
I highly recommend you have a read through the AsyncTask class documentation and the Processes and Threads article.

It is clear form the name indeed AsyncTask runs Asynchronously ...
Let me explain taking your code into consideration:
new get_pendingreq().execute();
This line will create a new thread for execution and it will run
asynchronously and so the next line(i.e.System.out.print("alalala" +
globalVariables.pendingdate.size());) gets executed immidiatly after this line without waiting the async task to get executed completly.so put this system.print line inside
the post execute method...

Are u sure, that globalVariables.pendingdate.add(e.getString("date")); realy have field "data" ?

Related

Suggestion about AsyncTask

In this topic:
About task onPostExecute
I asked about onPostExecute to dismiss a process, the friend #inner_class7 give me the way to resolve the error, but the friend #Doug Stevenson said that using this way the code will blocking the uithread, I tested and this is true, my uithraed was blocked. So He said that I need to use onPostExecute to get the result. I read about and created a code and I would like suggestion about.
I changed the code and do it:
protected ArrayList<String> doInBackground(String... params) {
try {
final String POST_PARAMS = params[1];
URL obj = new URL(params[0]);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("User-Agent", "Mozilla/5.0");
// For POST only - START
con.setDoOutput(true);
OutputStream os = con.getOutputStream();
os.write(POST_PARAMS.getBytes());
os.flush();
os.close();
// For POST only - END
int responseCode = con.getResponseCode();
System.out.println("POST Response Code :: " + responseCode);
if (responseCode == HttpURLConnection.HTTP_OK) { //success
BufferedReader in = new BufferedReader(new InputStreamReader(
con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
// print result
System.out.println(response.toString());
JSONArray myListsAll= new JSONArray(response.toString());
for(int i=0;i<myListsAll.length();i++){
JSONObject jsonObject = myListsAll.getJSONObject(i);
this.stringArray.add(jsonObject.toString());
}
} else {
System.out.println("POST request not worked");
}
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return this.stringArray;
}
#Override
protected void onPostExecute(ArrayList<String> result)
{
this.obj.setFeedsData(result);
if(setProgress){ progress.dismiss(); }
}
So call in my mainactivity:
#Override
protected void onCreate(Bundle savedInstanceState) {
String[] itensUrl = {links.feedsList(),"iduser=2&offset=0"};
new JsonRequest(this,this,true).execute(itensUrl);
}
public void setFeedsData(ArrayList<String> obj){
createListView(obj);
}
So what Do you think about? This way that a use is a good way?
What you have should be working just fine. You are correctly executing and parsing the results of the request off the UI thread. However, there are a couple minor things you can do to make it clearer.
stringArray looks like a field on the AsyncTask. This is not necessary the way you have the AsyncTask defined since you are already passing the stringArray directly into the onPostExecute() method. You should instead declare stringArray directly in the doInBackground() method.
Other thing I noticed is it looks like you might be keeping a reference to your Activity in the AsyncTask based on what you are doing in onPostExecute(). You are calling this.obj.setFeedsData(result);. If your AsyncTask is an inner class of the Activity using it you can call setFeedsData(result); directly instead.
If your AsyncTask is not an inner class it is usually best to pass the results back to the object interested in them through an interface in case you need to reuse the AsyncTask elsewhere.

Asynctask doInBackground is too slow on real device

I am developing an android application, I am new to thread and i apologize if my question is stupid, I used AsyncTask`s doInBackground method for converting Stream to String and then in onPostExecute method,app will begetting JSON Object.
I launched my application in Emulator (API 17) and it launched prefect but when I am launching it on my smart phone (galaxy s5) it is taking too long,maybe 10 or 15 seconds.
I think doInBackground method is causing this problem.
This is my Main Class and doing all here :
This is where i call my Asynctask Class and send a parameter with POST method :
final ArrayList<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("register_number", phoneNumber.getText().toString()));
Log.i("LOG", "params hastttttttttt" + params.toString());
//
// Commands.readRegisterNumber(params);
// new readData().execute(params);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
new readData().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
} else {
new readData().execute(params);
}
I define my Asynctask class here :
private class readData extends AsyncTask<List<? extends NameValuePair>, Void, String>
doInBackground method of Asynctask Class :
#Override
protected String doInBackground(List<? extends NameValuePair>... params) {
List<? extends NameValuePair> param = params[0];
try {
HttpClient client = new DefaultHttpClient();
HttpPost method = new HttpPost("http://192.168.10.110:2233/api/register");
method.setEntity(new UrlEncodedFormEntity(param));
HttpResponse response = client.execute(method);
InputStream inputStream = response.getEntity().getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder builder = new StringBuilder();
String line = "";
while ((line = reader.readLine()) != null) {
builder.append(line);
}
result = builder.toString();
}
catch (IOException e) {
e.printStackTrace();
}
return result;
}
and here is onPostExecute method :
#Override
protected void onPostExecute(String result) { //doInBackground khorujish ro mide be in
if (result != null) {
try {
G.registerNumber.clear();
JSONObject object = new JSONObject(result);
StructRegisterNumber structRegisterNumber = new StructRegisterNumber();
structRegisterNumber.status = object.optString("status");
structRegisterNumber.code = object.optString("code");
structRegisterNumber.message = object.optString("message");
G.registerNumber.add(structRegisterNumber);
StructRegisterNumber registerNumber = G.registerNumber.get(0);
if (registerNumber.status != null && registerNumber.code != null) {
if (Integer.parseInt(registerNumber.status) == -1) {
Intent intent = new Intent(ActivityRegisterNumber.this, ActivityRegisterCode.class);
ActivityRegisterNumber.this.startActivity(intent);
}
}
progressDialog.dismiss();
}
catch (JSONException e) {
e.printStackTrace();
}
} else {
progressDialog.dismiss();
}
}
There are many reason why it may be slow on a real device:
On a real device network speed will depend on the available wifi/network range and is more susceptible to packet loss.
On a real device multiple applications will be running simultaneously and background thread has lower priority than services and other applications. I would recommend using SDK tool Systrace (with sched option) to see CPU cycles received by the background thread.
This is not exactly solving your problem but as you are simply loading data from the network in your AsyncTask you should consider using a networking library such as Volley which makes live a lot easier. They even have support for Gson that can automatically parse your returned Json to objects automatically.
Documentation:
https://developer.android.com/training/volley/index.html
Library itself:
https://android.googlesource.com/platform/frameworks/volley

Continuous connection via HttpGet?

Hey all I am writing an android aplication which gets a JSON object from a node.js server. My code is below (I do not have access to the server code). Is there any way to consistently check the server for a change in the JSON object (if they update it)? Right now it only does one GET and stops. I want to be able to query for a change and continue working with the new updates. Thoughts? Thanks.
Called from OnCreate():
new Read().execute("JSONkey");
Here is my Read ASyncTask:
public class Read extends AsyncTask<String, Integer, String>{
#Override
protected String doInBackground(String...param) {
try {
read_json = getCoords();
httpText.append(read_json.toString() + "\n");
try{
}catch(Exception e){ e.printStackTrace(); }
JSONArray data = read_json.getJSONArray(param[0]);
for (int i = 0; i < data.length(); ++i){
JSONObject info = data.getJSONObject(i);
Coordinate pt = new Coordinate(info.getInt("point"), info.getString("name"), info.getDouble("lat"), info.getDouble("long"));
coords.put(pt.getPoint(), pt);
coordList.add(new GeoPoint(pt.getLat(),pt.getLong()));
}
return "Success"; //get "text"
} catch (Exception e){
return "Fail";
}
}
#Override
protected void onPostExecute(String result){
//Doing something with JSON
//new Read().execute("coords"); tried doing this, but I feel it is not right.
}
}
and the GetCoords():
public JSONObject getCoords()
throws ClientProtocolException, IOException, JSONException{
StringBuilder url = new StringBuilder(URL);
HttpGet get = new HttpGet(url.toString());
HttpResponse response = client.execute(get);
int status = response.getStatusLine().getStatusCode();
if(status == 200){
HttpEntity entity = response.getEntity();
String data = EntityUtils.toString(entity);
JSONObject last = new JSONObject(data);
return last;
}else{
return null;
}
}
The proper way to do this is with a WebSocket but given the constrain of not being able to control the server side, your best bet is to
Put your code inside a service:
http://developer.android.com/reference/android/app/IntentService.html
Then use the Alarm Manager to schedule periodic updates.
http://developer.android.com/reference/android/app/AlarmManager.html

NullPointer Exception while retrieving data from JSON [duplicate]

This question already has answers here:
NetworkOnMainThreadException [duplicate]
(5 answers)
Closed 8 years ago.
I'm trying to get data from my server using JSON and put the retrieved data to arrays
this is the fonction to retrieve category,intitule,id_news,images
public void getNewsFromServer(int beg){
InputStream is = null;
String result = "";
ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("beg", Integer.toString(beg)));
try {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(strURL);
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
is = entity.getContent();
} catch (Exception e) {
Toast.makeText(context, e.toString(), Toast.LENGTH_LONG).show();
}
// conversion of the query into string
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(is,
"iso-8859-1"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
is.close();
result = sb.toString();
} catch (Exception e) {
Toast.makeText(context, e.toString(),Toast.LENGTH_LONG).show();
}
try {
JSONArray jArray = new JSONArray(result);
for (int i = 0; i < jArray.length(); i++) {
JSONObject json_data = jArray.getJSONObject(i);
id_news[i] = Integer.toString(json_data.getInt("id_news"));
categorie[i] = json_data.getString("categorie");
intitule[i] = json_data.getString("intitule");
image[i] = json_data.getString("image");
}
}catch (Exception e){
Toast.makeText(context, e.toString(),
Toast.LENGTH_LONG).show();
}
}
And this the MainActivity.java
String [] id_news= new String [20];
String [] categorie= new String [20];
String [] intitule= new String [20];
String [] image= new String [20];
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
try{
//get data from the server and put it in tables
getNewsFromServer(beg);
}catch(NullPointerException e)
{
Toast.makeText(this, e.toString(), Toast.LENGTH_LONG).show();
e.getStackTrace();
}
}
but i always get NULLPointerException
help please
these the logCat trace
this the initialisation of the context Context context = this;
but it generate another exceptions NetworkOnMainThreadException and NullPointerException and JSONException:End of input at character 0..
The NPE comes from Toast initialization. Make sure the context you pass there is not null.
Since you use the toasts in exception catch blocks, log the exception stacktraces with e.g. e.printStackTrace() to get a hold on the root cause. (Prime suspect: NetworkOnMainThreadException)
For NetworkOnMainThreadException, do your network ops on a background thread. See How to fix android.os.NetworkOnMainThreadException? for more.
In your call to Toast, the context variable is most likely null.
Never catch a NullPointerException. Make sure it never gets thrown.
As laalto points out the NPE is coming in Toast statement.
Can you give a code snippet of how you have initialized context.
Also try using getActivity() there once and see if it solves the issue.
If it does then override onAttach() and initialize your context inside it. As directly giving getActivity() is not a good practice.
NetworkOnMainThreadException is caused because you should make network calls on a separate thread.
use something like:
Thread thread = new Thread()
{
#Override
public void run() {
try {
//your network calls here
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
thread.start();
i fixe the problem by using the AsynkTask
private class Asyn_GetNewsFromServer extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
getNewsFromServer(beg);
return null;
}
#Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
//do what ever you want
}
}
thx for your help

Scope of Variables in Java

In a Java Class, I have three List as fields in a class.
So I believe I made them available to the whole class? and all inner classes?
However, this does not work:
(For the example, I will only show one list here, not all three)
class Items extends ListActivity {
List<String> items = null; // field
Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// stuff
items = new ArrayList<String>();
new Task().execute();
Log.d("Size", String.valueOf(items.size()));
}
class Task extends AsyncTask<String, String, Void> {
// in this subclass, I parse items from JSON and add to List "items".
items = add(item);
}
Once I exit the task, I seem to lose the items in the List. It Logs "size 0"; if I do it inside the task, it shows the proper amount of items. Am I missing a very basic point about the scope of List variables here?
EDIT: Below is the complete Task class (slightly cleaned up for posting)
class Task extends AsyncTask<String, String, Void> {
private InputStream is = null;
private String result = "";
#Override
protected Void doInBackground(String... params) {
String url_select = "items.php";
param = new ArrayList<NameValuePair>();
param.add(new BasicNameValuePair("category", Category));
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url_select);
try {
httpPost.setEntity(new UrlEncodedFormEntity(param));
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
// read content
is = httpEntity.getContent();
} catch (Exception e) {
Log.e("log_tag", "Error in http connection " + e.toString());
}
try {
BufferedReader br = new BufferedReader(
new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = "";
while ((line = br.readLine()) != null) {
sb.append(line + "\n");
}
is.close();
result = sb.toString();
} catch (Exception e) {
// TODO: handle exception
Log.e("log_tag", "Error converting result " + e.toString());
}
return null;
}
protected void onPostExecute(Void v) {
try {
JSONArray jArray = new JSONArray(result);
JSONObject json_data = null;
for (int i = 0; i < jArray.length(); i++) {
json_data = jArray.getJSONObject(i);
item = json_data.getString("item");
items.add(item);
Log.d("Items", item);
}
} catch (JSONException e1) {
Toast.makeText(getBaseContext(), "No items!",
Toast.LENGTH_SHORT).show();
} catch (ParseException e1) {
e1.printStackTrace();
}
}
}
I am not Android developer but isn't AsyncTask something like new Thread? If yes then you just see "size 0" because Log.d("Size", String.valueOf(items.size())); was executed before new task().execute(); updated your list.
You'll want to read through this tutorial
Basically, the default access level is package private (I could be wrong on the description), but basically it means that so long as you're in the same package you can see the member, but it is not visible to sub classes.
Try using the protected access level instead

Categories

Resources