ListView中的数据库错误:应用已停止

时间:2013-06-23 14:46:11

标签: android listview android-asynctask

我有一个ListView,我在Android中加载MySQL DataBase中的所有项目并显示这些项目。由于列表需要更新,在活动中我使用Asynctask函数每15秒刷新一次并更新ListView。还有一个滚动条,因为可能有很多项目,这里是错误发生的地方。如果我通过滚动条上下移动它会很顺利。但是,如果我使用滚动条并且活动尝试访问数据库以加载更新的项目,则应用程序将停止。

这是日志:

   06-23 15:36:32.867: E/AndroidRuntime(7788): FATAL EXCEPTION: main
    06-23 15:36:32.867: E/AndroidRuntime(7788): java.lang.IndexOutOfBoundsException: Invalid index 14, size is 0
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:251)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at java.util.ArrayList.get(ArrayList.java:304)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.widget.SimpleAdapter.bindView(SimpleAdapter.java:147)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.widget.SimpleAdapter.createViewFromResource(SimpleAdapter.java:126)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.widget.SimpleAdapter.getView(SimpleAdapter.java:114)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.widget.AbsListView.obtainView(AbsListView.java:2445)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.widget.ListView.makeAndAddView(ListView.java:1769)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.widget.ListView.fillUp(ListView.java:706)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.widget.ListView.fillGap(ListView.java:645)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.widget.AbsListView.trackMotionScroll(AbsListView.java:5530)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.widget.AbsListView.scrollIfNeeded(AbsListView.java:3509)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.widget.AbsListView.onTouchEvent(AbsListView.java:3906)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.view.View.dispatchTouchEvent(View.java:7340)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2179)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1914)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2185)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1928)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2185)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1928)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2185)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1928)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2185)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1928)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2185)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1928)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2113)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1466)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.app.Activity.dispatchTouchEvent(Activity.java:2468)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2061)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.view.View.dispatchPointerEvent(View.java:7525)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.view.ViewRootImpl.deliverPointerEvent(ViewRootImpl.java:3368)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:3300)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:4392)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:4370)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:4474)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:171)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.view.InputEventReceiver.nativeConsumeBatchedInputEvents(Native Method)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.view.InputEventReceiver.consumeBatchedInputEvents(InputEventReceiver.java:163)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.view.ViewRootImpl.doConsumeBatchedInput(ViewRootImpl.java:4442)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.view.ViewRootImpl$ConsumeBatchedInputRunnable.run(ViewRootImpl.java:4493)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.view.Choreographer$CallbackRecord.run(Choreographer.java:725)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.view.Choreographer.doCallbacks(Choreographer.java:555)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.view.Choreographer.doFrame(Choreographer.java:523)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:711)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.os.Handler.handleCallback(Handler.java:615)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.os.Handler.dispatchMessage(Handler.java:92)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.os.Looper.loop(Looper.java:137)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at android.app.ActivityThread.main(ActivityThread.java:4895)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at java.lang.reflect.Method.invokeNative(Native Method)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at java.lang.reflect.Method.invoke(Method.java:511)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:994)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:761)
    06-23 15:36:32.867: E/AndroidRuntime(7788):     at dalvik.system.NativeStart.main(Native Method)

感谢您的帮助

编辑:以下是我每隔15秒刷新Listview的代码: @override

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.all_candidatos);
        StrictMode.ThreadPolicy policy = new StrictMode. ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy);

        boolean isReachable = false;
        try{
            isReachable = InetAddress.getByName("192.168.1.41").isReachable(200);
        } catch (Exception e){
            Log.e("InetAddress", e.getMessage());




        }finally {
            if (isReachable) {

                new CargarCandidatos().execute();
        timer();


            }else{
                Toast.makeText(getApplicationContext(), R.string.errorserver, Toast.LENGTH_LONG).show();
            }

        }
        setListAdapter(adapter);

        candidatosList = new ArrayList<HashMap<String, String>>();



    }
//
//  
    public void timer(){
         new CountDownTimer(tiempo, 1000) {

                public void onTick(long millisUntilFinished) {

                }

                public void onFinish() {
                    candidatosList.clear();
                    new CargarCandidatos().execute();


                    timer();

                }
             }.start();}




    class CargarCandidatos extends AsyncTask<String, Void, String> {


        @Override
        protected void onPreExecute() {
            if(!isFinishing()){
            super.onPreExecute();
            pDialog = new ProgressDialog(Monitorizacion.this);
            pDialog.setMessage("Monitorizando ...");
            pDialog.setIndeterminate(false);
            pDialog.setCancelable(false);
            pDialog.show();
        }
        }


        protected String doInBackground(String... args) {




                try {
                    monitorizar();
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();}
                return null;




        }


        protected void onPostExecute(String file_url) {
    pDialog.dismiss();
            runOnUiThread(new Runnable() {
                public void run() {

                    adapter = new SimpleAdapter(
                            Monitorizacion.this, candidatosList,
                            R.layout.list_item, new String[] { TAG_NSERIE,
                                    TAG_DNI, TAG_NOMBRE, TAG_TEST, TAG_PREGUNTA, TAG_BATERIA,TAG_CORRECTAS, TAG_ERRORES},
                            new int[] { R.id.id, R.id.dni, R.id.nombre, R.id.test, R.id.pregunta, R.id.bateria, R.id.correctas, R.id.fallos});

                    adapter.notifyDataSetChanged();
                    setListAdapter(adapter);


                }
            });

        }

    }
    public void monitorizar() throws Exception{
        try {
            List<NameValuePair> params = new ArrayList<NameValuePair>();
            JSONObject json = jParser.makeHttpRequest(url_candidatos, "GET", params);
            int success = json.getInt(TAG_SUCCESS);

            if (success == 1) {

                candidatos = json.getJSONArray(TAG_CANDIDATOS);

                for (int i = 0; i < candidatos.length(); i++) {
                    JSONObject c = candidatos.getJSONObject(i);

                    String nserie = c.getString(TAG_NSERIE);
                    String dni = c.getString(TAG_DNI);
                    String nombre = c.getString(TAG_NOMBRE);
                    String test = c.getString(TAG_TEST);
                    String pregunta = c.getString(TAG_PREGUNTA);
                    String bateria = c.getString(TAG_BATERIA);
                    String correctas = c.getString(TAG_CORRECTAS);
                    String errores = c.getString(TAG_ERRORES);

                    HashMap<String, String> map = new HashMap<String, String>();

                    map.put(TAG_NSERIE, nserie);
                    map.put(TAG_DNI, dni);
                    map.put(TAG_NOMBRE, nombre);
                    map.put(TAG_TEST, test);
                    map.put(TAG_PREGUNTA, pregunta);
                    map.put(TAG_BATERIA, bateria);
                    map.put(TAG_CORRECTAS, correctas);
                    map.put(TAG_ERRORES, errores);
                    candidatosList.add(map);
                }
            } 
        } catch (JSONException e) {
            e.printStackTrace();
        }



    }
}

编辑: 问题是,如果我向上或向下滚动Listview,并且在那时调用asynctask函数来访问数据库,则会发生错误并且应用程序停止。

Michael Butscher解决方案: 根据我的理解,我用Michael Butscher给出的建议解决了这个问题:

    public void timer(){
         new CountDownTimer(tiempo, 1000) {

                public void onTick(long millisUntilFinished) {

                }

                public void onFinish() {
                    new CargarCandidatos().execute();


                    timer();

                }
             }.start();}




    class CargarCandidatos extends AsyncTask<String, Void, String> {


        @Override
        protected void onPreExecute() {
            if(!isFinishing()){
            super.onPreExecute();
            pDialog = new ProgressDialog(Monitorizacion.this);
            pDialog.setMessage("Monitorizando ...");
            pDialog.setIndeterminate(false);
            pDialog.setCancelable(false);
            pDialog.show();
        }
        }


        protected String doInBackground(String... args) {




                try {
                    monitorizar();
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();}
                return null;




        }


        protected void onPostExecute(String file_url) {
    pDialog.dismiss();
            runOnUiThread(new Runnable() {
                public void run() {

                    adapter = new SimpleAdapter(
                            Monitorizacion.this, candidatosList,
                            R.layout.list_item, new String[] { TAG_NSERIE,
                                    TAG_DNI, TAG_NOMBRE, TAG_TEST, TAG_PREGUNTA, TAG_BATERIA,TAG_CORRECTAS, TAG_ERRORES},
                            new int[] { R.id.id, R.id.dni, R.id.nombre, R.id.test, R.id.pregunta, R.id.bateria, R.id.correctas, R.id.fallos});

                    adapter.notifyDataSetChanged();
                    setListAdapter(adapter);



                }
            });

        }

    }
    public void monitorizar() throws Exception{
        try {
            List<NameValuePair> params = new ArrayList<NameValuePair>();
            JSONObject json = jParser.makeHttpRequest(url_candidatos, "GET", params);
            ArrayList<HashMap<String, String>> temp;
            temp = new ArrayList<HashMap<String, String>>();


            int success = json.getInt(TAG_SUCCESS);

            if (success == 1) {

                candidatos = json.getJSONArray(TAG_CANDIDATOS);

                for (int i = 0; i < candidatos.length(); i++) {
                    JSONObject c = candidatos.getJSONObject(i);

                    String nserie = c.getString(TAG_NSERIE);
                    String dni = c.getString(TAG_DNI);
                    String nombre = c.getString(TAG_NOMBRE);
                    String test = c.getString(TAG_TEST);
                    String pregunta = c.getString(TAG_PREGUNTA);
                    String bateria = c.getString(TAG_BATERIA);
                    String correctas = c.getString(TAG_CORRECTAS);
                    String errores = c.getString(TAG_ERRORES);

                    HashMap<String, String> map = new HashMap<String, String>();

                    map.put(TAG_NSERIE, nserie);
                    map.put(TAG_DNI, dni);
                    map.put(TAG_NOMBRE, nombre);
                    map.put(TAG_TEST, test);
                    map.put(TAG_PREGUNTA, pregunta);
                    map.put(TAG_BATERIA, bateria);
                    map.put(TAG_CORRECTAS, correctas);
                    map.put(TAG_ERRORES, errores);
                    temp.add(map);
                    candidatosList = temp;
                }
            } 
        } catch (JSONException e) {
            e.printStackTrace();
        }



    }
}

1 个答案:

答案 0 :(得分:1)

onPostExecute()中,您创建了一个获取candidatosList作为数据的适配器。 SimpleAdapter现在预计只有在事后立即调用notifyDataSetChanged()时才会更改此数据(更改和调用仅在主线程上发生)。

在您的计时器的onFinish()中,您拨打candidatosList.clear()onFinish()在主线程上运行,这样就可以了)但您没有拨打notifyDataSetChanged()

更好的方法:

根本不要致电candidatosList.clear(),而是在ArrayList开头创建一个新的temp(例如名为“monitorizar()”),并填写收到的数据,作为monitorizar()设置candidatosList = temp的最后一步。为了在所有情况下都能正常工作,candidatosList应该声明volatile(因为它被多个线程使用)。