0

This is what I essentially want to do, but can't. I want the value of urlData and size to be updated from the inner class functions. The app is crashing by giving a Null Pointer Exception at the line where I try to access these variables from the CreateTextView() function.

package edu.ahduni.seas.gyapak;

import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;

import org.json.JSONException;
import org.json.JSONArray;
import org.json.JSONObject;

import android.util.Log;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    public ArrayList<Data> urlData; //Culprit 1
    public int size; //no. of dirs + files, Culprit 2
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void parseJSON() throws JSONException {
        ParseActivity parse = new ParseActivity();
        String url = "RDovQWNhZGVtaWMvU2FuamF5IENoYXVkaGFyeQ==";
        parse.execute(url);
        CreateTextView();
        Log.e("RETURNING JSON","RETURNING");
    }

    public void CreateTextView() {
        TextView text = (TextView) findViewById(R.id.text);
        text.setText(Integer.toString(size));
        Button myButton = new Button(this);
        if(urlData==null) //workaround for crash
            return;
        myButton.setText(urlData.get(0).getName());

        LinearLayout ll = (LinearLayout)findViewById(R.id.textlayout);
        LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
                                                                    LinearLayout.LayoutParams.WRAP_CONTENT);
        ll.addView(myButton, lp);
    }

    class ParseActivity extends AsyncTask<String, Void, ArrayList<Data>> {
        InputStream is = null;
        JSONArray jObj = null;
        String json = "";


        @Override
        public void onPostExecute(ArrayList<Data> data) {
            size = data.size(); //here!
        }

        @Override
        protected ArrayList<Data> doInBackground(String... params) {
            final String BASE_URL = "http://111.93.66.162/json/main.php?f=" + params[0];
            HttpURLConnection urlConnection;

            // Making HTTP request
            try {

                Log.e("OPENING: ", "URL");
                URL url = new URL(BASE_URL);

                urlConnection = (HttpURLConnection) url.openConnection();
                urlConnection.setRequestMethod("GET");
                urlConnection.connect();

                is = urlConnection.getInputStream();

                StringBuffer buffer = new StringBuffer();
                if (is == null) {
                    // Nothing to do.
                    return null;
                }

                BufferedReader in = new BufferedReader(new InputStreamReader(is));
                String line;

                while ((line = in.readLine()) != null) {
                    buffer.append(line + "\n");
                    Log.e("JSON: ", line);
                }
                if (buffer.length() == 0) {
                    // Stream was empty.  No point in parsing.
                    return null;
                }
                is.close();
                json = buffer.toString();

            } catch (Exception e) {
                e.printStackTrace();
            }

            try {
                return getData(json);
            } catch (JSONException e) {
                e.printStackTrace();
            }
            return null;
        }

        public ArrayList<Data> getData(String jsonString) throws JSONException {
            // try parse the string to a JSON object
            final String EXT = "ext";
            final String PATH = "path";
            final String NAME = "name";

            try {
                jObj = new JSONArray(jsonString);
            } catch (JSONException e) {
                e.printStackTrace();
            }

            urlData = new ArrayList<Data>();

            for (int i=0;i<jObj.length();i++) {
                JSONObject obj = jObj.getJSONObject(i);
                String ext = obj.getString(EXT);
                String path = obj.getString(PATH);
                String name = obj.getString(NAME);

                urlData.add(new Data(ext,path,name)); //and here!
            }
            return urlData;
        }
    }
}
burglarhobbit
  • 1,860
  • 2
  • 17
  • 32
  • What problem are you facing exactly? "but can't" is quite vague. Your code seems to be compiling and working fine (at least in Java 8). – Pshemo Aug 29 '16 at 18:39
  • Use ```abcd.c``` in ```void ok()``` method. – Sanket Makani Aug 29 '16 at 18:39
  • I am not Android developer so I can't help you much, but main problem of NPE is explained here: http://stackoverflow.com/q/218384/1393766. For better help consider including full stacktrace. Here is info about how you can debug your code based on it: http://stackoverflow.com/q/3988788/1393766. – Pshemo Aug 29 '16 at 19:00
  • The best advice I can give you is; instead of returning `null` from `doInBackground` return an empty list. This `null` seems to be passed to `onPostExecute` which is crashing the program. – Jorn Vernee Aug 29 '16 at 19:31
  • @JornVernee That part is fool proof. It was already tested earlier. – burglarhobbit Aug 29 '16 at 19:32
  • @Mr.Robot Looking at [the doc](https://developer.android.com/reference/android/os/AsyncTask.html): _"`onPostExecute(Result)`, invoked on the UI thread after the background computation finishes. The result of the background computation [`doInBackground`] is passed to this step as a parameter."_. So when you return `null`, it is indeed passes to `onPostExecute`, where you (try to) dereference it, thus throwing a `NullPointerException`. – Jorn Vernee Aug 29 '16 at 19:36
  • @JornVernee `null` is not being returned from the doInBackground process, it is returning `getData(json)` even my log files can confirm that. – burglarhobbit Aug 29 '16 at 19:44
  • @Mr.Robot Ok, well, you could still try if retuning an empty list instead of `null` helps. Otherwise, you could try replacing `size = data.size();` with `size = (data == null ? 0 : data.size());` – Jorn Vernee Aug 29 '16 at 19:56

1 Answers1

1

The inner class is not static, so it needs an instance of the enclosing class to be instantiated. Like so:

public class abcd {
    static int x;

    public static void main(String[] args) {
        abcd o = new abcd(); // Create instance of abcd called 'o'
        abcd.efgh o2 = o.new efgh(); // Use instance 'o' to create an instance of efgh

        System.out.println(x); // 0
        o2.ok();
        System.out.println(x); // 5 
    }

    class efgh {
        public void ok() {
            x = 5;
        }
    }
}
Jorn Vernee
  • 31,735
  • 4
  • 76
  • 93