Java.lang.IllegalStateException:适配器的内容已更改,但ListView未收到通知

时间:2013-04-26 08:03:41

标签: android android-listview android-arrayadapter

我从我的应用收到该错误消息。但我认为我的ListView是从UIThread实现的,因为我有这段代码:

ListaOrdenesActivity.this.runOnUiThread(new Runnable() {
        public void run() {
            aAdapter=new SubnotsAdapter(c, 0, subnots);         
            setListAdapter(aAdapter);
            aAdapter.notifyDataSetChanged();

        }
});

这是设置适配器的活动:

public class ListaOrdenesActivity extends ListActivity {

Context c;
int id;
ArrayList<SubNotificacion> subnots=new ArrayList<SubNotificacion>();
Handler aHandler=new Handler();
SubnotsAdapter aAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.listaordeneslayout);
    c=getApplicationContext();
    id=getIntent().getExtras().getInt("id");
    General.campaignid=id;
    for(int i=0;i<General.arraynot.size();i++){
        if(General.arraynot.get(i).id==this.id){
            subnots=General.arraynot.get(i).subnotificacion;

        }
    }

    for (int i=0;i<subnots.size();i++){
        General.ids.add(subnots.get(i).id);
    }
    ListaOrdenesActivity.this.runOnUiThread(new Runnable() {
        public void run() {
            aAdapter=new SubnotsAdapter(c, 0, subnots);         
            setListAdapter(aAdapter);
            aAdapter.notifyDataSetChanged();

        }
});
    if(aAdapter!=null){
    aAdapter.notifyDataSetChanged();
    }
    ImageView sos=(ImageView)findViewById(R.id.botonordenessos);
    ImageView home=(ImageView)findViewById(R.id.botonordeneshome);
    home.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {

            Intent home=new Intent(c,HomeActivity.class);
            startActivity(home);

        }
    });

}

}

适配器:

public class SubnotsAdapter extends ArrayAdapter {

ArrayList<SubNotificacion> objects=new ArrayList<SubNotificacion>();
Context context;
SimpleDateFormat format=new SimpleDateFormat("dd/MM/yyyy");
int idNoti;
int idSubnoti;

@Override
public int getCount() {
    // TODO Auto-generated method stub
    return objects.size();
}

@Override
public Object getItem(int position) {
    // TODO Auto-generated method stub
    return this.objects.get(position);
}

@Override
public long getItemId(int position) {
    // TODO Auto-generated method stub
    return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View v = convertView;
    if (v == null) {

                LayoutInflater vi = (LayoutInflater) context
                        .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                v = vi.inflate(R.layout.subnotadapterlayout, null);
            }
    final SubNotificacion subnot=objects.get(position);
    TextView lugar=(TextView)v.findViewById(R.id.textolugar);
    lugar.setText(subnot.direccion);
    TextView fecha=(TextView)v.findViewById(R.id.textofechasubnoti);
    fecha.setText(format.format(subnot.dia).toString());
    ImageView flecha=(ImageView)v.findViewById(R.id.flechasubnotadapter);
    flecha.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {

            Intent detalle=new Intent(context,SubnotDetailActivity.class);
            detalle.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            detalle.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
            detalle.putExtra("idsubnoti", subnot.id);
            detalle.putExtra("idnoti", General.campaignid);
            context.startActivity(detalle);
        }
    });
    return v;
}

@SuppressWarnings("unchecked")
public SubnotsAdapter(Context context, int textViewResourceId,
        ArrayList objects) {
    super(context, textViewResourceId, objects);
    this.objects=objects;
    this.context=context;

}

}

如果我在UIThread中运行它...为什么我收到该错误消息?怎么解决?昨天我整整一天都遇到了这个问题...我认为今天会是一样的。

请帮忙!谢谢。

编辑:

完整的堆栈跟踪:

04-26 09:51:32.785: E/AndroidRuntime(30726): FATAL EXCEPTION: main
04-26 09:51:32.785: E/AndroidRuntime(30726): java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. [in ListView(16908298, class android.widget.ListView) with Adapter(class com.publidirecta.vinceriazafata.SubnotsAdapter)]
04-26 09:51:32.785: E/AndroidRuntime(30726):    at android.widget.ListView.layoutChildren(ListView.java:1514)
04-26 09:51:32.785: E/AndroidRuntime(30726):    at android.widget.AbsListView$CheckForTap.run(AbsListView.java:2096)
04-26 09:51:32.785: E/AndroidRuntime(30726):    at android.os.Handler.handleCallback(Handler.java:587)
04-26 09:51:32.785: E/AndroidRuntime(30726):    at android.os.Handler.dispatchMessage(Handler.java:92)
04-26 09:51:32.785: E/AndroidRuntime(30726):    at android.os.Looper.loop(Looper.java:130)
04-26 09:51:32.785: E/AndroidRuntime(30726):    at android.app.ActivityThread.main(ActivityThread.java:3701)
04-26 09:51:32.785: E/AndroidRuntime(30726):    at java.lang.reflect.Method.invokeNative(Native Method)
04-26 09:51:32.785: E/AndroidRuntime(30726):    at java.lang.reflect.Method.invoke(Method.java:507)
04-26 09:51:32.785: E/AndroidRuntime(30726):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
04-26 09:51:32.785: E/AndroidRuntime(30726):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:624)
04-26 09:51:32.785: E/AndroidRuntime(30726):    at dalvik.system.NativeStart.main(Native Method)

因为它没有显示我的代码所在的位置,我猜它是在唯一的地方设置适配器...我把它放在UIThread ...

创建子标记的位置:

public class NotificationService extends Service {

private Timer timer=new Timer();
int icono=android.R.drawable.stat_sys_warning;
String estado="Ha recibido una nueva notificación";
long hora = System.currentTimeMillis();
Context c;
StringBuilder builder = new StringBuilder();
CustomHttpClient client = new CustomHttpClient();
String url;
String response="";
CharSequence titulo = "Oferta de trabajo!";
CharSequence descripcion = "Ha recibido una nueva oferta";
//Cada notificación del sistema tiene una id, en nuestro caso ésta será la id. Se utiliza para diferenciarla de las notificaciones del resto de 
//aplicaciones, por ejemplo, para borrarla. En nuestro caso, eliminaremos la notificación cuando a) el usuario haga click en ella o b) el usuario haga click
//en el widget (Véase la clase StartJob.java)
public static int NOTIF_ID=5;
AppWidgetManager manager;
//String urljson;
ArrayList<SubNotificacion> listasub=new ArrayList<SubNotificacion>();
SubNotificacion subnot;
double salario;
String localidad;
String desc;
Notificacion not;
Notificacion check;
String nombre;
int id;
int duracion;
String respuesta="no";
String provincia;
Bitmap logo;
byte[] array;
String fechainicio;
@Override
public IBinder onBind(Intent intent) {

    return null;
}

@Override
public void onCreate() {

    super.onCreate();
    url=getString(R.string.host)+getString(R.string.appnamespace)+getString(R.string.urlcheckjob);//parametros: nombre:azafata valor:usuario
    url=getString(R.string.host)+getString(R.string.appnamespace)+"personal/pendientes";
    c=getApplicationContext();
    //Método que lanza el servicio
    lanzarServicio();

}

private void lanzarServicio() {

    timer.scheduleAtFixedRate(
              new TimerTask() {
                @Override
                public void run() {


                    //Log.i("LOGIN", "Lo que tenemos en respuesta: "+respuesta);
                    if(respuesta!="no"){
                        Log.i("LOGIN", "respuesta!=no");
                        //respuesta=lanzarPeticion();
                        check=parsearJSON(respuesta);
                        if(check.nombre!=null){
                        General.arraynot.add(check);
                        Log.i("LOGIN", "Campaña añadida al array de General");
                        General.arraytodas=General.arraynot;
                        //Configuramos el servicio de notificaciones    
                        String ns = Context.NOTIFICATION_SERVICE;       
                        Intent notIntent=new Intent(c, AlertsActivity.class);       
                        PendingIntent contIntent = PendingIntent.getActivity(
                                c, 0, notIntent, 0);
                        Builder notif = new NotificationCompat.Builder(c);
                        synchronized (notif) {

                            notif.setContentIntent(contIntent)
                                    .setWhen(System.currentTimeMillis())
                                    .setTicker("Notification ticker")
                                    .setSmallIcon(R.drawable.ic_launcher)
                                    .setContentTitle("Vinceri")
                                    .setContentText("Ha recibido una oferta de trabajo")
                                    .setAutoCancel(true);

                            Notification notification = notif.build();
                              //get instance of NotificationManager
                              NotificationManager notificationmanager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
                              //call notify method of NotificationManager to add this notification to android notification drawer..
                              notificationmanager.notify(0, notification);
                              //respuesta=lanzarPeticion();
                    }




    }       
    }
                    Log.i("LOGIN", "Lanzamos la petición");
                    respuesta=lanzarPeticion();

                }                   
              }

              ,
              0,
              20000);

}

private String lanzarPeticion(){
            Log.i("LOGIN", "Método lanzarPeticion()");
    //En los parámetros, hemos de enviar el usuario, para que el server compruebe si hay trabajos para ese usuario en concreto
            ArrayList <NameValuePair> parameters=new ArrayList<NameValuePair>();
            //El usuario se ha almacenado en la clase estática "General"
            parameters.add(new BasicNameValuePair("azafata", General.getUsuario()));

            try {
                //Lanzamos la petición


                    //lanzarServicio();
                    respuesta=CustomHttpClient.executeHttpPost(url, parameters);
                    respuesta= respuesta.replaceAll("\\s+","");
                    Log.i("LOGIN", "la respuesta: "+respuesta);





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

            }

    return respuesta;

}

private Notificacion parsearJSON(String json){
    try {
        JSONObject resp=new JSONObject(json);
        Log.i("JSON", "Contenido del JSONObject: "+resp.toString());
        JSONObject trabajos=new JSONObject(resp.getString("trabajos"));
        JSONObject orden=new JSONObject(trabajos.getString("ordenTrabajo"));
        desc=orden.getString("descripcion");
        salario=orden.getDouble("salario");
        localidad=orden.getString("localidad");
        nombre=orden.getString("nombre");
        id=orden.getInt("id");
        duracion=orden.getInt("duracion");
        provincia=orden.getString("provincia");
        fechainicio=orden.getString("fechaInicio");

        String jsonar=orden.getString("foto");



        array=Base64.decode(jsonar, Base64.DEFAULT);
        logo=BitmapFactory.decodeByteArray(array, 0, array.length);

        JSONArray array=new JSONArray(orden.getString("subOrden"));
        SimpleDateFormat recibido=new SimpleDateFormat("yyyy-MM-dd");
        //SimpleDateFormat mostrar =new SimpleDateFormat("dd-MM-yyyy");

        for(int i=0; i<array.length();i++){

            JSONObject sub=array.getJSONObject(i);

            if(sub!=null){
            try {

                subnot=new SubNotificacion(sub.getString("inicio"),  
                                           recibido.parse(sub.getString("fecha")), 
                                           sub.getString("direccion"),
                                           sub.getInt("id"));

            } catch (ParseException e) {

                e.printStackTrace();

            }
            listasub.add(subnot);


        }
        }


    } catch (JSONException e) {

        e.printStackTrace();
    }

    not=new Notificacion(desc, listasub, salario, localidad, nombre, id, duracion, provincia, logo, fechainicio);
    return not;

}

protected void cambiarIcono() {

    //Si el usuario está logueado, lanzamos el intent.
    if(General.isIsloggedin()){

        //Lanzamos un intent personalizado para nuestro widget, mediante un BroadCast que será interceptado por nuestro Widget provider (que no deja de ser un BroadcastReceiver)
        Intent notIntent=new Intent("com.publidirecta.Azafatas.ACTUALIZAR_WIDGET");
        c.sendBroadcast(notIntent);
    }
}


}

和Subnotificacion类:

public class SubNotificacion {

String inicio;  
Date dia;
String direccion;
int id;

public SubNotificacion(String inicio, Date dia, String direccion, int id) {


    this.inicio = inicio;   
    this.dia = dia;
    this.direccion = direccion;
    this.id=id;
}


}

1 个答案:

答案 0 :(得分:0)

尝试找出 subnots 类的“设置方法”。 “set methods”表示更改或修改对象数据的方法。

您正在对 SubnotsAdapter 中传递的数据进行一些更改。因此,找出您使用 subnots 数组列表的位置。