在 Activity 的“onCreate”方法中从在线 MySQL DB 获取数据

Posted

技术标签:

【中文标题】在 Activity 的“onCreate”方法中从在线 MySQL DB 获取数据【英文标题】:Getting data from online MySQL DB in "onCreate" method of Activity 【发布时间】:2018-04-27 23:40:52 【问题描述】:

我正在开发需要从在线 mysql 数据库获取数据并将其显示为活动布局中的列表的应用程序。

问题是我的应用程序出现错误“尝试在空对象引用上调用接口方法'int java.util.List.size()'”

在 onCreate 方法中,我调用 asyncTask 类以从服务器获取数据,然后在该代码行下方,我通过适配器将该数据设置为我的布局的 listview。 开始该活动时,我收到错误消息。

我应该在启动 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);

编辑:

我按照大家的建议修复了它,现在没有错误,活动打开,但它仍然没有显示来自在线数据库的任何数据.. 这里编辑 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 类:

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

(" ") 中的那些字符串必须是小写字母,因为我在 PHP 中就是这样写的。

感谢大家的帮助。

【问题讨论】:

你在哪里初始化了一个 invoices 对象? @Alex Nik 在开始时,在 onCreate 方法之上 onStart 在 onCreate 方法之后调用。您应该在将集合传递给适配器之前对其进行初始化 在 logcat 中截取您的堆栈跟踪。它有望为我们提供更多信息 另外,我怀疑您的列表将是空的,因为在 INvoiceDownloader 中无法访问适配器 【参考方案1】:

您应该通过适配器将数据设置为 asyncTask 的 onPostExecute() 上的 listview。 (https://developer.android.com/reference/android/os/AsyncTask.html)

由于任务是异步的,您正试图在服务器响应到达之前访问发票列表的数据。

【讨论】:

我将此答案标记为最接近我的解决方案,但这里提供的所有答案都是相似的,对我来说都是正确的。再次感谢 heisen、@trocchietto 和 Alex Nik。【参考方案2】:

可能您没有收到服务器的回复,这就是列表为空的原因,编辑发布堆栈跟踪并能够更好地帮助您,看看这个post 它看起来同样的问题你有,原因是在调用网络服务(SQL db) 我的猜测是你的堆栈跟踪的第二行说 ArrayAdapter.getCount() 因为通常是这里的问题,返回列表的 ArrayAdapter 调用的方法,在你的情况下是 null 因为不从服务器检索。可能是 JsonException,所以你应该添加一个带有 try catch 的异常来管理如果服务器没有检索到响应会发生什么。

 public int   getCount() 


    return mObjects.size();


Async 任务比 3 年前少用了,现在几乎所有社区都使用 Retrofit 进行异步调用以及 RXJava

【讨论】:

【参考方案3】:

您正在将未初始化的集合(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);

然后在 onPostExecute 中的 AsyncTask 中填充新项目并调用 adapter.notifyDataSetChanged

【讨论】:

我按照大家的建议修复了,不是没有错误,打开没问题,但仍然没有显示数据库中的任何数据

以上是关于在 Activity 的“onCreate”方法中从在线 MySQL DB 获取数据的主要内容,如果未能解决你的问题,请参考以下文章

多次调用“activity.onCreate()”方法是不是正常

在 Activity 的“onCreate”方法中从在线 MySQL DB 获取数据

Android Activity 中 onCreate 方法第二个实现有啥用?

Android查缺补漏(View篇)--在 Activity 的 onCreate() 方法中为什么获取 View 的宽和高为0?

Activity在onCreate和onResume中finish时,生命周期的不同表现

java中onCreate()方法是干啥用的