2017-07-14 1 views
0

Ich versuche, eine Aktivität mit recyclerview neuen Daten erhalten jedes Mal SQLite zu aktualisieren (SQLite die Daten tatsächlich von einem TCP-Client-Signal erhalten) hier ist mein RecyclerView Code:Refresh RecyclerView in Echtzeit nach neuen Daten zu SQLite Hinzufügen

public static class ViewHolder extends RecyclerView.ViewHolder{ 
    public TextView data_txt; 
    public TextView text_txt; 
    public TextView ora_txt; 
    public ImageView img; 

    public ViewHolder(final View itemView) { 
     super(itemView); 

     data_txt = itemView.findViewById(R.id.Data); 
     ora_txt = itemView.findViewById(R.id.Ora); 
     text_txt = itemView.findViewById(R.id.Errore); 
     img = itemView.findViewById(R.id.error_photo); 
    } 

} 
private List<Adapter> mText; 

public RecyclerViewAdapter(Context c,List<Adapter> testo) { 
    this.c = c; 
    mText = testo; 

} 


@Override 
public RecyclerViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
    View contactView = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_blueprint, parent, false); 
    return new ViewHolder(contactView); 
} 

@Override 
public void onBindViewHolder(RecyclerViewAdapter.ViewHolder viewHolder, int position) { 
    Adapter adapter = mText.get(position); 

    TextView mData = viewHolder.data_txt; 
    mData.setText(adapter.getDataText()); 

    TextView mOra = viewHolder.ora_txt; 
    mOra.setText(adapter.getOraText()); 

    TextView mTesto = viewHolder.text_txt; 
    mTesto.setText(adapter.getTesto()); 

    ImageView mImg = viewHolder.img; 
    mImg.setImageBitmap(adapter.getImage()); 
} 

@Override 
public int getItemCount() { 
    return mText.size(); 
} 

public void removeItem(int position) { 

    Adapter a = mText.get(position); 
    int id=a.getId(); 

    DataBaseHandler myDB; 
    myDB = DataBaseHandler.getInstance(c); 
    myDB.openDB(); 
    if(myDB.delete(id)) 
    { 
     mText.remove(position); 
    }else 
    { 
     Toast.makeText(c,"Unable To Delete", Toast.LENGTH_SHORT).show(); 
    } 
    myDB.closeDB(); 
    this.notifyDataSetChanged(); 
} 

wenn ich versuche RecyclerView mit RecyclerViewAdapter.notifyDataSetChanged();, wenn der TCP-Server die Daten erhalten, die Crash mit Fehler zu aktualisieren:

java.lang.NullPointerException: Attempt to invoke virtual method 'void com.example.sguidetti.selfmanegment.RecyclerViewAdapter.notifyDataSetChanged()' on a null object reference 

EDIT: Hier Code ist, wo ich anrufen notifyDataSet Chande() in TCP-Server-Klasse:

Vibrator vibrator; 
    String date,ora; 
    long[] pattern = {0, 1000, 500, 1000, 500, 1000}; 

    int lun; 

    @Override 
    public void run() { 
     InputStream leggi; 
     try { 


      serverSocket = new ServerSocket(socketServerPORT); 

      while (true) { 
       myDB = DataBaseHandler.getInstance(activity); 

       Socket socket = serverSocket.accept(); 
       leggi = socket.getInputStream(); 
       byte[] data = new byte[1000]; 
       lun = leggi.read(data, 0, data.length); 
       letto = new String(data, "UTF-8"); 
       count++; 
       MediaPlayer mPlay = MediaPlayer.create(activity, R.raw.gabsuono); 
       mPlay.start(); 

       vibrator = (Vibrator) activity.getSystemService(VIBRATOR_SERVICE); 
       vibrator.vibrate(pattern, -1); 

       date = new SimpleDateFormat("dd-MM-yyyy").format(new Date()); 
       ora = new SimpleDateFormat("HH:mm:ss").format(new Date()); 



       myDB.insertDataServer(date, ora, letto); 

       adapterView.notifyDataSetChanged(); 

       activity.runOnUiThread(new Runnable() { 
        @Override 
        public void run() { 
         prefs = activity.getSharedPreferences("MY_DATA", MODE_PRIVATE); 
         SharedPreferences.Editor edit = prefs.edit(); 
         edit.putInt("counter", count); 
         edit.commit(); 
         activity.msg.setText(String.valueOf(count)); 
         activity.msg.setVisibility(View.VISIBLE); 

        } 
       }); 
       leggi.close(); 


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

     } 

und hier ist die Tätigkeit, bei der ich die RecyclerView nennen:

DataBaseHandler myDB; 
RecyclerView recyclerView; 
RecyclerViewAdapter adapterView; 
ImageButton home; 
String IMGSTRING; 
Adapter adapter; 
List<Adapter> textList; 
private Paint p = new Paint(); 


@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_allert); 
    Utils.darkenStatusBar(this, R.color.colorAccent); 
    myDB = DataBaseHandler.getInstance(this); 
    home = (ImageButton) findViewById(R.id.casa); 
    recyclerView = (RecyclerView) findViewById(R.id.recyclerview); 
    Bitmap img; 
    img = BitmapFactory.decodeResource(getResources(), R.drawable.allert); 
    Cursor data = myDB.fetchDataServer(); 
    textList = new ArrayList<>(); 
    int cont = 0; 
    if (data.getCount() != 0) { 
     while (data.moveToNext()) { 


      IMGSTRING = data.getString(3).substring(0, 3); 


      switch (IMGSTRING) { 
       case "X00": 
        img = BitmapFactory.decodeResource(getResources(), R.drawable.allert); 
        break; 
       case "E01": 
        img = BitmapFactory.decodeResource(getResources(), R.drawable.e01); 
        break; 
       case "E02": 
        img = BitmapFactory.decodeResource(getResources(), R.drawable.e02); 
        break; 
       case "E03": 
        img = BitmapFactory.decodeResource(getResources(), R.drawable.e03); 
        break; 
       case "E90": 
        img = BitmapFactory.decodeResource(getResources(), R.drawable.e90); 
        break; 
       case "E04": 
        img = BitmapFactory.decodeResource(getResources(), R.drawable.e04); 
        break; 
       case "E05": 
        img = BitmapFactory.decodeResource(getResources(), R.drawable.e04); 
        break; 
       case "E06": 
        img = BitmapFactory.decodeResource(getResources(), R.drawable.e04); 
        break; 
      } 


      adapter = new Adapter(data.getInt(0), data.getString(1), data.getString(2), data.getString(3).substring(3), img); // 1 = time 2 = data 3 = text 


      textList.add(cont, adapter); 
      cont++; 

     } 
     RecyclerViewAdapter recycler = new RecyclerViewAdapter(this, textList); 
     recyclerView.setAdapter(recycler); 
     recyclerView.setLayoutManager((new LinearLayoutManager(this))); 
    } else { 
     Toast.makeText(allert.this, "NESSUN MESSAGGIO DA VISUALIZZARE!", Toast.LENGTH_LONG).show(); 
    } 
    adapterView = new RecyclerViewAdapter(this, textList); 
    recyclerView.setAdapter(adapterView); 
    adapterView.notifyDataSetChanged(); 
    initSwipe(); 
    home.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View view) { 
      finish(); 
     } 
    }); 
} 

private void initSwipe() { 
    ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) { 

     @Override 
     public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { 
      return false; 
     } 

     @Override 
     public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { 
      int position = viewHolder.getAdapterPosition(); 
      adapterView.removeItem(position); 


     } 

     @Override 
     public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { 

      Bitmap icon; 
      if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) { 

       View itemView = viewHolder.itemView; 
       float height = (float) itemView.getBottom() - (float) itemView.getTop(); 
       float width = height/3; 

       p.setColor(Color.parseColor("#D32F2F")); 
       RectF background = new RectF((float) itemView.getRight() + dX, (float) itemView.getTop(), (float) itemView.getRight(), (float) itemView.getBottom() - 10); 
       c.drawRect(background, p); 
       icon = BitmapFactory.decodeResource(getResources(), R.drawable.ic_delete_white); 
       RectF icon_dest = new RectF((float) itemView.getRight() - 2 * width, (float) itemView.getTop() + width, (float) itemView.getRight() - width, (float) itemView.getBottom() - width); 
       c.drawBitmap(icon, null, icon_dest, p); 

      } 
      super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); 
     } 
    }; 
    ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleItemTouchCallback); 
    itemTouchHelper.attachToRecyclerView(recyclerView); 
} 
+0

Aufruf 'notifyDataSetChanged' von Fragment, in dem Sie RecyclerView verwenden –

+0

von wo rufen Sie" notifyDataSetChanged() "? Sie müssen sicherstellen, dass Ihre Referenz auf den Adapter nicht null ist. Ich würde untersuchen, wo der Anruf getätigt wird. – paligap

+0

Es gibt noch ein notifyDataSetChange im Layout, wo ich es benutze, aber immer noch nicht funktioniert, ich meine, wenn ich in dieser Aktivität für die Aktualisierung neuer RecyclerView-Nachrichten bin, muss ich von dieser Aktivität beenden und es erneut eingeben. (Entschuldigung für mein schlechtes Englisch) –

Antwort

0

Könnten Sie einen Null-Check hier haben?

@Override 
public int getItemCount() { 
    return mText != null ? mText.size() : 0; 
} 

Meine beste Vermutung der Grund ist, dass Sie notifyDataSetChanged() aufrufen, wenn mText noch null ist. Wenn notifyDataSetChanged() aufgerufen wird, wird getItemCount() zuerst aufgerufen, um zu überprüfen, ob die aktuelle Position in der Liste innerhalb der Größe Ihrer "mText" -Liste liegt, aber es wird einen Absturz verursachen, da mText null ist.

Zwei Dinge, die Sie auf removeItem() -Methode verbessern könnte:

  1. Statt Aufruf this.notifyDataSetChanged(), rufen this.notifyItemRemoved (Position) als onBindViewHolder() nicht aufgerufen werden n-mal (n = Anzahl der Zeilen, die derzeit in Ihrem RecyclerView angezeigt werden)
  2. Mischen Sie Ihren Datenbankcode nicht mit Ihrem UI-Code. Ihre RecyclerView.Adapter-Klasse sollte sich nur mit UI-Logik- und UI-Statusobjekten (in diesem Fall mText) befassen. Mit anderen Worten,

    public void removeItem(int position) { 
        mText.remove(position); 
        this.notifyItemRemoved(position); 
    } 
    

in Ihrer MainActivity Klasse, rufen removeItem() zusätzlich zu Ihrem Datenbank-Code.

+0

Yeah eigentlich mText in RecyclerViewAdapter und in Adapter ist null und das wird nur in einer anderen Aktivität füllen Daten aus der Datenbank, wie könnte ich es beheben? weil ich diesen mText wirklich als leer initialisieren muss ... –

+0

Vielleicht haben Sie einen asynchronen Rückruf und rufen Sie this.notifyDataSetChanged() nur in Ihrer Rückrufmethode auf? (Bevor Daten an mText übergeben werden, natürlich) – Thearith

0

Sie müssen sicherstellen, dass der Adapter initialisiert wird, bevor die notifyDataSetChanged() -Methode aufgerufen wird. Ein alternativer Ansatz besteht darin, eine Methode in der Adapterklasse hinzuzufügen, in der Sie die ArrayList übergeben und notifyDataSetChanged() aufrufen können.

+0

könnten Sie bitte ein Beispiel für die ArrayList machen? –

+0

/** * Methode im Adapter fügen die neuesten Meldungen aus der Datenbank hinzu. * @param notificationsArrayList */ public void updateAdapter (List notificationsArrayList) {try { Logger.logd ("Size", notificationsList.size() + ""); notificationsList.addAll (notificationsArrayList); notifyDataSetChanged(); } catch (Ausnahme e) { e.printStackTrace(); } } Fügen Sie dies in Aktivität hinzu. notificationsListRecycleAdapter.updateAdapter (notificationsList); –

Verwandte Themen