簡體   English   中英

嘗試從json數組生成android listview

[英]Trying to generate an android listview from a json array

所以我當前的活動類中有以下代碼:

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

有人可以告訴我我要去哪里了,因為我只是新來的。

問題僅在於您在doInBackgroud()方法中創建了對象包裝........並且您嘗試在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();

    }

你應該搬家

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

在后台執行操作,並將其作為全局變量。

提取完數據后,可以在onPost execute中設置適配器。 您的列表視圖永遠不會初始化,因此會出現空指針異常。

以下是我在您的代碼中發現的錯誤,並且我也嘗試修復該錯誤。

您應該在onCreate()初始化所有視圖和適配器。

uploadChore()complete() ,不要為將數據傳遞給其他方法而啟動相同的活動,而uploadChore()其作為參數傳遞。

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

字符串響應= stringBuilder.toString(); JSONObject jsonResponse =新的JSONObject(response);

檢查響應應該像這樣:{“ chore”:[{“ chore_name”:“ name”,“ child_username”:“ username”,“ point_value”:“ value”},{“ chore_name”:“ name”,“ child_username “:”用戶名“,” point_value“:”值“}]}

原因:

問題不在於設置適配器,而在於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並更正它們。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM