[英]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.