【问题标题】:Trying to generate an android listview from a json array试图从 json 数组生成一个 android listview
【发布时间】:2016-03-14 11:44:13
【问题描述】:

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

@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)

谁能告诉我哪里出了问题,因为我只是新手。

【问题讨论】:

  • 在看这个之前,请提供整个异常跟踪。在“致命异常:主”消息之后肯定有一个堆栈跟踪?
  • 创建一个全局变量 "choreList" 并写 choreList = (ListView) findViewById(R.id.choreList);在 onCreate 方法而不是 doInBackground 中。
  • 使用jsonlint.com检查你的json响应是否有效
  • 很明显,wrapper.list.setAdapter(wrapper.myArrayAdapter);您没有在实例化属性(列表)上设置适配器,您必须实例化您的列表并提供给适当的视图。
  • 问题不在于设置适配器,而在于 JSON 格式。

标签: android android-asynctask fatal-error


【解决方案1】:

问题只是你在 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();

    }

【讨论】:

    【解决方案2】:

    你应该搬家

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

    在后台执行之外并将它们作为全局变量。

    获取数据后,您可以将适配器设置为 onPost 执行。您的列表视图从未初始化,因此会出现空指针异常。

    【讨论】:

      【解决方案3】:

      字符串响应 = stringBuilder.toString(); JSONObject jsonResponse = new JSONObject(response);

      检查响应 它应该是这样的: { “家务”:[{ “家务名称”:“名称”, "child_username": "用户名", “point_value”:“价值” }, { “家务名称”:“名称”, "child_username": "用户名", “point_value”:“价值” }] }

      【讨论】:

        【解决方案4】:

        原因:

        问题不在于设置适配器,而在于 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 对象,最后一个NPE 被抛出。

        解决方案:

        您应该检查您从服务器获取的 JSON 并更正它们。

        【讨论】:

          【解决方案5】:

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

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

          uploadChore()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);
                  }
              });
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2013-12-07
            • 1970-01-01
            • 1970-01-01
            • 2019-04-22
            • 2017-10-11
            • 2021-07-22
            • 2021-04-21
            • 1970-01-01
            相关资源
            最近更新 更多