试图从json数组生成一个android listview

时间:2016-03-14 11:44:14

标签: android android-asynctask fatal-error

所以我在当前的活动类中有以下代码:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_chores);

    bChore = (Button) findViewById(R.id.addChore);

    bChore.setOnClickListener(this);

    Bundle extras = getIntent().getExtras();
    final String user = extras.getString("username");



   fillInBackground();
}

@Override
public void onClick(View v) {

    Bundle extras = getIntent().getExtras();
    final String user = extras.getString("username");

    switch (v.getId()) {
        case R.id.addChore:
            name = (EditText) findViewById(R.id.choreName);
            value = (EditText) findViewById(R.id.points);
            String choreTitle = name.getText().toString();
            int pointValue = Integer.parseInt(value.getText().toString());
            try {
                if (choreTitle.length() <= 0)
                    Toast.makeText(Chores.this, "Please enter a chore", Toast.LENGTH_SHORT).show();
                else {
                    if (pointValue == 0)
                        Toast.makeText(Chores.this, "Please enter a valid number", Toast.LENGTH_SHORT).show();
                    else {
                        Chore chore = new Chore(choreTitle, pointValue, user);
                        uploadChore(chore);
                        break;
                    }
                }
            } catch (NumberFormatException e) {
                Toast.makeText(Chores.this, "Please enter a valid point value", Toast.LENGTH_SHORT).show();
            }
    }
}

private void fillInBackground() {


    new AsyncTask<Void, Void, Wrapper>() {


        Bundle extras = getIntent().getExtras();
        final String user = extras.getString("username");
        @Override
        protected Wrapper doInBackground(Void... params) {
            String requestURL = SERVER_ADDRESS + "FetchChoreData.php";
            ListView choreList = (ListView) findViewById(R.id.choreList);
            ArrayList<String> chores = new ArrayList<>();
            Wrapper wrapper = new Wrapper();

             String headings = "Chore" + "\t" + "Child" + "\t" + "Points";
             chores.add(headings);

            URL url;
            try {
                //Opens the connection to the PHP files
                //Sets the conditions of the connection
                url = new URL(requestURL);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setReadTimeout(CONNECTION_TIMEOUT);
                conn.setConnectTimeout(CONNECTION_TIMEOUT);
                conn.setRequestMethod("POST");
                conn.setDoInput(true);
                conn.setDoOutput(true);

                //Opens an output stream to send the data to be verified
                // and then closes the all output streams and flushes the output writer
                OutputStream os = conn.getOutputStream();
                BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));

                Uri.Builder builder = new Uri.Builder()
                        .appendQueryParameter("username", user);

                String query = builder.build().getEncodedQuery();

                writer.write(query);
                writer.flush();
                writer.close();
                os.close();
                //saves the response code to ensure connection was succesful
                int code = conn.getResponseCode();
                Log.d("code", Integer.toString(code));

                //Opens an input stream to retrieve verified data back from the server
                //Starts a String Builder to read the data off the input
                //Closes the BufferedReader once it has finished building the string
                InputStream responseStream = new BufferedInputStream(conn.getInputStream());
                BufferedReader responseStreamReader = new BufferedReader(new InputStreamReader(responseStream));
                String line;
                StringBuilder stringBuilder = new StringBuilder();
                while ((line = responseStreamReader.readLine()) != null)
                    stringBuilder.append(line + "/n");
                responseStreamReader.close();


                String response = stringBuilder.toString();
                Log.d("response", response);

                JSONObject jsonResponse = new JSONObject(response);

                //Creates a JSON object from the string

                JSONArray choresArray = jsonResponse.getJSONArray("chore");
                for (int i = 0; i < choresArray.length(); i++) {
                    JSONObject chore = choresArray.getJSONObject(i);
                    String current_chore = chore.optString("chore_name");
                    String name = chore.optString("child_username");
                    String points = chore.optString("point_value");

                    String currentChore = "";
                    if (name == null)
                        currentChore = current_chore + "\t" + "Not Claimed" + "\t" + points;
                    else
                        currentChore = current_chore + "\t" + name + "\t" + points;
                    chores.add(currentChore);
                    Log.d("Output", currentChore);

                }

                wrapper.myArrayAdapter = new ArrayAdapter<>(Chores.this,  android.R.layout.simple_list_item_1, chores);
                wrapper.list = choreList;



            } catch (Exception e) {
                e.printStackTrace();
            }
            return wrapper;
        }
        protected void onPostExecute(Wrapper wrapper) {
            //After the previous method executes we end the process dialog
            //and we return the user call back and return the verified user
            wrapper.list.setAdapter(wrapper.myArrayAdapter);
        }
    }.execute();

}




private void uploadChore(Chore chore) {
    Bundle extras = getIntent().getExtras();
    final String user = extras.getString("username");
    //Implements the ServerRequest class to register the user details
    ServerRequests serverRequests = new ServerRequests(this);
    //Checks that the details are valid and what account type it is setting up
    serverRequests.storeChoreData(chore,new GetUserCallBack() {
        //What is done when the user has successfully registered
        @Override
        public void complete(User returnedUser) {
            Intent chores = new Intent(Chores.this, Chores.class);
            chores.putExtra("username", user);
            startActivity(chores);
        }
    });
}

}

包装器类如下所示:

public class Wrapper {
     public ListView list;
     public ArrayAdapter<String> myArrayAdapter;
}

然而,当我运行应用程序时,它会停止并且我得到以下致命异常:

W/System.err: org.json.JSONException: Value <!DOCTYPE of type java.lang.String cannot be converted to JSONObject
03-14 11:54:17.493 18935-19311/com.jack.pointcollector W/System.err:     at org.json.JSON.typeMismatch(JSON.java:111)
03-14 11:54:17.493 18935-19311/com.jack.pointcollector W/System.err:     at org.json.JSONObject.<init>(JSONObject.java:160)
03-14 11:54:17.493 18935-19311/com.jack.pointcollector W/System.err:     at org.json.JSONObject.<init>(JSONObject.java:173)
03-14 11:54:17.494 18935-19311/com.jack.pointcollector W/System.err:     at com.jack.pointcollector.Chores$1.doInBackground(Chores.java:149)
03-14 11:54:17.494 18935-19311/com.jack.pointcollector W/System.err:     at com.jack.pointcollector.Chores$1.doInBackground(Chores.java:89)
03-14 11:54:17.494 18935-19311/com.jack.pointcollector W/System.err:     at android.os.AsyncTask$2.call(AsyncTask.java:295)
03-14 11:54:17.494 18935-19311/com.jack.pointcollector W/System.err:     at java.util.concurrent.FutureTask.run(FutureTask.java:237)
03-14 11:54:17.494 18935-19311/com.jack.pointcollector W/System.err:     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234)
03-14 11:54:17.494 18935-19311/com.jack.pointcollector W/System.err:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
03-14 11:54:17.494 18935-19311/com.jack.pointcollector W/System.err:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
03-14 11:54:17.494 18935-19311/com.jack.pointcollector W/System.err:     at java.lang.Thread.run(Thread.java:818)
03-14 11:54:17.581 18935-18935/com.jack.pointcollector D/AndroidRuntime: Shutting down VM
03-14 11:54:17.581 18935-18935/com.jack.pointcollector E/AndroidRuntime: FATAL EXCEPTION: main Process: com.jack.pointcollector, PID: 18935
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ListView.setAdapter(android.widget.ListAdapter)' on a null object reference
at     com.jack.pointcollector.Chores$1.onPostExecute(Chores.java:183)
at     com.jack.pointcollector.Chores$1.onPostExecute(Chores.java:89)
at     android.os.AsyncTask.finish(AsyncTask.java:651)
at     android.os.AsyncTask.-wrap1(AsyncTask.java)
at     android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:668)
at     android.os.Handler.dispatchMessage(Handler.java:102)
at     android.os.Looper.loop(Looper.java:148)
at     android.app.ActivityThread.main(ActivityThread.java:5417)
at     java.lang.reflect.Method.invoke(Native Method)
at     com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at     com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

有人可以告诉我我哪里出错了,因为我只是新手。

5 个答案:

答案 0 :(得分:0)

问题只是你在doInBackgroud()方法中创建了Object Wrapper ........然后你尝试访问onPostExecute()方法.......

        new AsyncTask<Void, Void, Wrapper>() {



            @Override
            protected Wrapper doInBackground(Void... params) {

                ListView choreList = (ListView) findViewById(R.id.choreList);
                ArrayList<String> chores = new ArrayList<>();

               // change this make them Global.....
                Wrapper wrapper = new Wrapper();


                    wrapper.myArrayAdapter = new ArrayAdapter<>(Chores.this,  android.R.layout.simple_list_item_1, chores);
                    wrapper.list = choreList;



                } catch (Exception e) {
                    e.printStackTrace();
                }
                return wrapper;
            }
            protected void onPostExecute(Wrapper wrapper) {
                //After the previous method executes we end the process dialog
                //and we return the user call back and return the verified user
                wrapper.list.setAdapter(wrapper.myArrayAdapter);
            }
        }.execute();

    }

答案 1 :(得分:0)

你应该移动

     ListView choreList = (ListView) findViewById(R.id.choreList);
        ArrayList<String> chores = new ArrayList<>();

在你的背景之外做,并将它们作为全球变量。

完成提取数据后,可以在onPost执行中设置适配器。您的列表视图从未初始化,因此空指针异常。

答案 2 :(得分:0)

以下是我在您的代码中发现的错误,我也尝试修复它。

您应该在onCreate()初始化所有视图和适配器。

uploadChore()&#39; complete()中,不要将数据传递给其他方法,而是将其作为参数传递。

ListView及其Adapter应在开头初始化。稍后,将数据添加到列表中并调用适配器notifyDataSetChanged()

ArrayList<String> chores;
Wrapper wrapper;

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_chores);

    bChore = (Button) findViewById(R.id.addChore);
    name = (EditText) findViewById(R.id.choreName);
    value = (EditText) findViewById(R.id.points);

    wrapper = new Wrapper();
    ListView choreList = (ListView) findViewById(R.id.choreList);
    chores = new ArrayList<>();
    wrapper.myArrayAdapter = new ArrayAdapter<>(Chores.this, android.R.layout.simple_list_item_1, chores);
    wrapper.list = choreList;
    wrapper.list.setAdapter(wrapper.myArrayAdapter);

    bChore.setOnClickListener(this);

}

@Override
public void onClick(View v)
{
    Bundle extras = getIntent().getExtras();
    final String user = extras.getString("username");

    switch (v.getId())
    {
        case R.id.addChore:

            String choreTitle = name.getText().toString();
            int pointValue = Integer.parseInt(value.getText().toString());
            try
            {
                if (choreTitle.length() <= 0)
                    Toast.makeText(Chores.this, "Please enter a chore", Toast.LENGTH_SHORT).show();
                else
                {
                    if (pointValue == 0)
                        Toast.makeText(Chores.this, "Please enter a valid number", Toast.LENGTH_SHORT).show();
                    else
                    {
                        Chore chore = new Chore(choreTitle, pointValue, user);
                        uploadChore(chore);
                        break;
                    }
                }
            }
            catch (NumberFormatException e)
            {
                Toast.makeText(Chores.this, "Please enter a valid point value", Toast.LENGTH_SHORT).show();
            }
    }
}

private void fillInBackground(String user)
{
    new AsyncTask<Void, String, Wrapper>()
    {

        @Override
        protected Wrapper doInBackground(Void... params)
        {
            String requestURL = SERVER_ADDRESS + "FetchChoreData.php";


            String headings = "Chore" + "\t" + "Child" + "\t" + "Points";
            publishProgress(headings);

            URL url;
            try
            {
                //Opens the connection to the PHP files
                //Sets the conditions of the connection
                url = new URL(requestURL);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setReadTimeout(CONNECTION_TIMEOUT);
                conn.setConnectTimeout(CONNECTION_TIMEOUT);
                conn.setRequestMethod("POST");
                conn.setDoInput(true);
                conn.setDoOutput(true);

                //Opens an output stream to send the data to be verified
                // and then closes the all output streams and flushes the output writer
                OutputStream os = conn.getOutputStream();
                BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));

                Uri.Builder builder = new Uri.Builder()
                        .appendQueryParameter("username", user);

                String query = builder.build().getEncodedQuery();

                writer.write(query);
                writer.flush();
                writer.close();
                os.close();
                //saves the response code to ensure connection was succesful
                int code = conn.getResponseCode();
                Log.d("code", Integer.toString(code));

                //Opens an input stream to retrieve verified data back from the server
                //Starts a String Builder to read the data off the input
                //Closes the BufferedReader once it has finished building the string
                InputStream responseStream = new BufferedInputStream(conn.getInputStream());
                BufferedReader responseStreamReader = new BufferedReader(new InputStreamReader(responseStream));
                String line;
                StringBuilder stringBuilder = new StringBuilder();
                while ((line = responseStreamReader.readLine()) != null)
                    stringBuilder.append(line + "/n");
                responseStreamReader.close();


                String response = stringBuilder.toString();
                Log.d("response", response);

                JSONObject jsonResponse = new JSONObject(response);

                //Creates a JSON object from the string

                JSONArray choresArray = jsonResponse.getJSONArray("chore");
                for (int i = 0; i < choresArray.length(); i++)
                {
                    JSONObject chore = choresArray.getJSONObject(i);
                    String current_chore = chore.optString("chore_name");
                    String name = chore.optString("child_username");
                    String points = chore.optString("point_value");

                    String currentChore = "";
                    if (name == null)
                        currentChore = current_chore + "\t" + "Not Claimed" + "\t" + points;
                    else
                        currentChore = current_chore + "\t" + name + "\t" + points;
                    publishProgress(currentChore);
                    Log.d("Output", currentChore);

                }

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

        @Override
        protected void onProgressUpdate(String... values)
        {
            super.onProgressUpdate(values);
            wrapper.list.add(values[0]);
        }

        protected void onPostExecute(Wrapper wrapper)
        {
            //After the previous method executes we end the process dialog
            //and we return the user call back and return the verified user
            wrapper.myArrayAdapter.notifyDataSetChanged();
        }
    }.execute();

}

private void uploadChore(Chore chore)
{
    Bundle extras = getIntent().getExtras();
    final String user = extras.getString("username");
    //Implements the ServerRequest class to register the user details
    ServerRequests serverRequests = new ServerRequests(this);
    //Checks that the details are valid and what account type it is setting up
    serverRequests.storeChoreData(chore, new GetUserCallBack()
    {
        //What is done when the user has successfully registered
        @Override
        public void complete(User returnedUser)
        {
            // Simple add data into the list. Don't start same activity again and again.
            fillInBackground(user);
        }
    });
}

答案 3 :(得分:0)

String response = stringBuilder.toString(); JSONObject jsonResponse = new JSONObject(response);

检查回复 应该是这样的: {     &#34;家务&#34;:[{         &#34; chore_name&#34;:&#34; name&#34;,         &#34; child_username&#34;:&#34;用户名&#34;,         &#34; point_value&#34;:&#34; value&#34;     },{         &#34; chore_name&#34;:&#34; name&#34;,         &#34; child_username&#34;:&#34;用户名&#34;,         &#34; point_value&#34;:&#34; value&#34;     }] }

答案 4 :(得分:0)

<强>原因:

问题不是设置适配器,而是使用JSON解析。根据您的错误日志

W/System.err: org.json.JSONException: Value <!DOCTYPE of type java.lang.String cannot be converted to JSONObject

您收到的字符串无法转换为JSONObject。发生此错误时,正在catch块中捕获并且到那时

wrapper.myArrayAdapter = new ArrayAdapter<>(Chores.this,  android.R.layout.simple_list_item_1, chores);
wrapper.list = choreList;

未被调用。这导致onPostExecute接收listview的null对象,最后抛出NPE

<强>解决方案:

您应该检查您获得表单服务器的JSON并更正它们。