在 Activity 的 "onCreate" 方法中从在线 MySQL 数据库获取数据
Getting data from online MySQL DB in "onCreate" method of Activity
我正在开发需要从在线 MySQL 数据库获取数据并将其显示为 activity 布局中的列表的应用程序。
问题是我的应用程序出现错误“尝试在空对象引用上调用接口方法 'int java.util.List.size()'”
在 onCreate 方法中,我调用 asyncTask class 从服务器获取数据,然后在该行代码下方,我通过适配器将该数据设置为列表视图,这是我的布局。
启动 activity 时,出现错误。
我应该在开始之前从服务器获取数据吗Activity?还是问题出在其他地方?
我的 php 文件在浏览器中检查时工作正常。
这里是onCreate方法:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.invoice_list);
final ListView listView1 = (ListView) findViewById(R.id.invoicelist);
InvoiceDownloader task = new InvoiceDownloader();
task.execute(new String[] { "http://10.0.2.2/company/getinvoices.php" });
ArrayAdapter<Invoice> adapter = new ArrayAdapter<Invoice>(this, android.R.layout.simple_list_item_1, invoices);
listView1.setAdapter(adapter);
}
编辑:
我按照大家的建议修复了它,现在没有错误,activity 打开了,但它仍然没有显示来自在线数据库的任何数据。
这里编辑了 onCreate() 方法:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.invoice_list);
adapter = new ArrayAdapter<Invoice>(this, android.R.layout.simple_list_item_1);
listView1 = (ListView) findViewById(R.id.invoicelist);
InvoiceDownloader task = new InvoiceDownloader();
task.execute(new String[] { "http://10.0.2.2/company/getinvoices.php" });
adapter.notifyDataSetChanged();
}
这是 AsyncTask class:
public class InvoiceDownloader extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... params) {
String response = "";
try {
response += getHttpContent(params[0]);
} catch (IOException e) {
Log.e("error", e.toString());
}
return response;
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
adapter.addAll(invoices);
listView1.setAdapter(adapter);
Toast.makeText(getApplicationContext(), s, Toast.LENGTH_SHORT).show();
}
public String getHttpContent(String urlStr) throws IOException {
String response = "";
try {
URL url = new URL(urlStr);
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
StringBuilder sb = new StringBuilder();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(httpConn.getInputStream()));
String json;
while ((json = bufferedReader.readLine()) != null) {
sb.append(json + "\n");
}
JSONArray jsonArray = new JSONArray(sb.toString().trim());
for (int i = 0; i < jsonArray.length(); i++) {
Invoice invoice = new Invoice();
JSONObject inv = jsonArray.getJSONObject(i);
String companyNameOne = inv.getString("companyNameOne");
String companyNameTwo = inv.getString("companyNameTwo");
String address = inv.getString("address");
String postalCode = inv.getString("postalCode");
String city = inv.getString("city");
String oib = inv.getString("oib");
String email = inv.getString("email");
int comple = inv.getInt("completed");
String completed = String.valueOf(comple);
String workOrderNumber = inv.getString("workOrderNumber");
String price = inv.getString("price");
System.out.println("Company Name 1: " + companyNameOne + " Company Name 2: " + companyNameTwo + " address: " + address + " postalCode: " + postalCode + " city: " + city + " oib: " + oib + " email: " + email + " completed: " + completed + " work order num: " + workOrderNumber + " price: " + price);
invoice.setCompanyNameOne(companyNameOne);
invoice.setCompanyNameTwo(companyNameTwo);
invoice.setAddress(address);
invoice.setPostalCode(postalCode);
invoice.setCity(city);
invoice.setOib(oib);
invoice.setEmail(email);
invoice.setCompleted(completed);
invoice.setWorkOrderNumber(workOrderNumber);
invoice.setPrice(price);
invoices.add(invoice);
}
return response;
} catch (Exception e) {
return null;
}
}
}
第二次编辑:
我明白了。抱歉,这个问题在修复错误后不显示数据是我的错误。这部分:
JSONObject inv = jsonArray.getJSONObject(i);
String companyNameOne = inv.getString("companyNameOne");
String companyNameTwo = inv.getString("companyNameTwo");
String address = inv.getString("address");
String postalCode = inv.getString("postalCode");
String city = inv.getString("city");
String oib = inv.getString("oib");
String email = inv.getString("email");
int comple = inv.getInt("completed");
String completed = String.valueOf(comple);
String workOrderNumber = inv.getString("workOrderNumber");
String price = inv.getString("price");
(" ") ALL 中的那些字符串必须是小写字母,因为我在 PHP.
中是这样写的
谢谢大家的帮助。
可能你没有得到服务器的回复,这就是列表为空的原因,编辑发布堆栈跟踪并且能够更好地帮助你,看看这个它看起来与您遇到的问题相同,原因在于对网络服务的调用(SQL db)
我的猜测是你的堆栈跟踪的第二行说 ArrayAdapter.getCount()
因为通常是这里的问题,ArrayAdapter 调用的方法 returns 一个列表,在你的情况下是 null 因为不从服务器检索。可能是 JsonException,因此您应该添加一个带有 try catch 的异常来管理如果服务器未检索到响应会发生什么。
public int getCount() {
return mObjects.size();
}
异步任务比 3 年前更少使用,现在几乎所有社区都在使用 Retrofit 进行异步调用以及 RXJava
您应该在 asyncTask 的 onPostExecute() 上通过适配器将数据设置为列表视图。 (https://developer.android.com/reference/android/os/AsyncTask.html)
由于任务是异步的,您正试图在服务器响应到达之前访问发票列表的数据。
您正在将未初始化的集合 (null) 传递到适配器中。这就是为什么当适配器尝试获取集合大小时您会收到 NullPointerException 的原因。
您需要这样做:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.invoice_list);
...
invoices = new ArrayList<>();
ArrayAdapter<Invoice> adapter = new ArrayAdapter<Invoice>(this, android.R.layout.simple_list_item_1, invoices);
listView1.setAdapter(adapter);
}
然后用 AsyncTask
的 onPostExecute
中的新项目填充集合并调用 adapter.notifyDataSetChanged
我正在开发需要从在线 MySQL 数据库获取数据并将其显示为 activity 布局中的列表的应用程序。
问题是我的应用程序出现错误“尝试在空对象引用上调用接口方法 'int java.util.List.size()'”
在 onCreate 方法中,我调用 asyncTask class 从服务器获取数据,然后在该行代码下方,我通过适配器将该数据设置为列表视图,这是我的布局。 启动 activity 时,出现错误。
我应该在开始之前从服务器获取数据吗Activity?还是问题出在其他地方? 我的 php 文件在浏览器中检查时工作正常。
这里是onCreate方法:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.invoice_list);
final ListView listView1 = (ListView) findViewById(R.id.invoicelist);
InvoiceDownloader task = new InvoiceDownloader();
task.execute(new String[] { "http://10.0.2.2/company/getinvoices.php" });
ArrayAdapter<Invoice> adapter = new ArrayAdapter<Invoice>(this, android.R.layout.simple_list_item_1, invoices);
listView1.setAdapter(adapter);
}
编辑:
我按照大家的建议修复了它,现在没有错误,activity 打开了,但它仍然没有显示来自在线数据库的任何数据。 这里编辑了 onCreate() 方法:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.invoice_list);
adapter = new ArrayAdapter<Invoice>(this, android.R.layout.simple_list_item_1);
listView1 = (ListView) findViewById(R.id.invoicelist);
InvoiceDownloader task = new InvoiceDownloader();
task.execute(new String[] { "http://10.0.2.2/company/getinvoices.php" });
adapter.notifyDataSetChanged();
}
这是 AsyncTask class:
public class InvoiceDownloader extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... params) {
String response = "";
try {
response += getHttpContent(params[0]);
} catch (IOException e) {
Log.e("error", e.toString());
}
return response;
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
adapter.addAll(invoices);
listView1.setAdapter(adapter);
Toast.makeText(getApplicationContext(), s, Toast.LENGTH_SHORT).show();
}
public String getHttpContent(String urlStr) throws IOException {
String response = "";
try {
URL url = new URL(urlStr);
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
StringBuilder sb = new StringBuilder();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(httpConn.getInputStream()));
String json;
while ((json = bufferedReader.readLine()) != null) {
sb.append(json + "\n");
}
JSONArray jsonArray = new JSONArray(sb.toString().trim());
for (int i = 0; i < jsonArray.length(); i++) {
Invoice invoice = new Invoice();
JSONObject inv = jsonArray.getJSONObject(i);
String companyNameOne = inv.getString("companyNameOne");
String companyNameTwo = inv.getString("companyNameTwo");
String address = inv.getString("address");
String postalCode = inv.getString("postalCode");
String city = inv.getString("city");
String oib = inv.getString("oib");
String email = inv.getString("email");
int comple = inv.getInt("completed");
String completed = String.valueOf(comple);
String workOrderNumber = inv.getString("workOrderNumber");
String price = inv.getString("price");
System.out.println("Company Name 1: " + companyNameOne + " Company Name 2: " + companyNameTwo + " address: " + address + " postalCode: " + postalCode + " city: " + city + " oib: " + oib + " email: " + email + " completed: " + completed + " work order num: " + workOrderNumber + " price: " + price);
invoice.setCompanyNameOne(companyNameOne);
invoice.setCompanyNameTwo(companyNameTwo);
invoice.setAddress(address);
invoice.setPostalCode(postalCode);
invoice.setCity(city);
invoice.setOib(oib);
invoice.setEmail(email);
invoice.setCompleted(completed);
invoice.setWorkOrderNumber(workOrderNumber);
invoice.setPrice(price);
invoices.add(invoice);
}
return response;
} catch (Exception e) {
return null;
}
}
}
第二次编辑:
我明白了。抱歉,这个问题在修复错误后不显示数据是我的错误。这部分:
JSONObject inv = jsonArray.getJSONObject(i);
String companyNameOne = inv.getString("companyNameOne");
String companyNameTwo = inv.getString("companyNameTwo");
String address = inv.getString("address");
String postalCode = inv.getString("postalCode");
String city = inv.getString("city");
String oib = inv.getString("oib");
String email = inv.getString("email");
int comple = inv.getInt("completed");
String completed = String.valueOf(comple);
String workOrderNumber = inv.getString("workOrderNumber");
String price = inv.getString("price");
(" ") ALL 中的那些字符串必须是小写字母,因为我在 PHP.
中是这样写的谢谢大家的帮助。
可能你没有得到服务器的回复,这就是列表为空的原因,编辑发布堆栈跟踪并且能够更好地帮助你,看看这个
public int getCount() {
return mObjects.size();
}
异步任务比 3 年前更少使用,现在几乎所有社区都在使用 Retrofit 进行异步调用以及 RXJava
您应该在 asyncTask 的 onPostExecute() 上通过适配器将数据设置为列表视图。 (https://developer.android.com/reference/android/os/AsyncTask.html)
由于任务是异步的,您正试图在服务器响应到达之前访问发票列表的数据。
您正在将未初始化的集合 (null) 传递到适配器中。这就是为什么当适配器尝试获取集合大小时您会收到 NullPointerException 的原因。 您需要这样做:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.invoice_list);
...
invoices = new ArrayList<>();
ArrayAdapter<Invoice> adapter = new ArrayAdapter<Invoice>(this, android.R.layout.simple_list_item_1, invoices);
listView1.setAdapter(adapter);
}
然后用 AsyncTask
的 onPostExecute
中的新项目填充集合并调用 adapter.notifyDataSetChanged