2017-01-19 6 views
0

Ich fülle eine RecyclerView mit bis zu mehreren tausend Einträgen aus einer sqlite database, geladen über eine AsyncTaskLoader. Die Liste muss filterbar sein, daher muss ich alle Einträge gleichzeitig laden. Einige der TextViews in den ViewHolders von RecyclerView enthalten Ergebnisse weiterer DB-Abfragen (basierend auf dem Anfangsergebnis) oder andere Arten von Berechnungen.RecyclerView lazy loading TextView Inhalt

Das Erweitern der anfänglichen Abfrage auf JOINs (was zumindest dazu führen würde, dass die sekundären Abfragen obsolet werden) verlangsamt das Laden wirklich. Das Ausführen der Abfragen/Berechnungen innerhalb der onBind-Methode des RecyclerViews macht das Schleudern jedoch viel weniger flüssig als ohne sie.

Gibt es eine Möglichkeit, den Inhalt für diese berechneten TextViews lazy zu laden? Ich habe nach Beispielen gesucht, aber Bibliotheken wie "Picasso" und "Glide" erlauben nur das Laden von Bildern ...

Jede Hilfe wird geschätzt!

Danke, Rob

+0

Verwendung [diese] (https://gist.github.com/Shywim/127f207e7248fe48400b) Adapter – pskink

+0

@pskink : Danke, aber dieser Adapter ist nicht wirklich meine Bedürfnisse ... – user1905169

+0

verwenden Sie einfach JOINS, und nein, zum Filtern müssen Sie nicht alle Einträge auf einmal laden, überschreiben Sie einfach 'runQueryOnBackgroundThread' oder richten Sie 'FilterQueryProvider' – pskink

Antwort

0

Ich landete mit einem Singleton Klasse eine ExecutorService mit meinem Laden/Berechnungen in separate Threads und dann mit der Handler Update mein ViewHolder zu tun. Ich weiß nicht, ob dies der beste Weg ist, aber bisher funktioniert es ohne irgendwelche Probleme.

private static class LazyLoadManager { 
    private static LazyLoadManager INSTANCE; 
    private final ExecutorService pool; 
    private Map<ViewHolder, String> viewHolders = Collections.synchronizedMap(new WeakHashMap<ViewHolder, String>()); 
    private Context context; 

    private LazyLoadManager(Context context) { 
     this.context = context; 
     pool = Executors.newFixedThreadPool(5); 
    } 

    public static LazyLoadManager getInstance(Context context) { 
     if (INSTANCE == null) { 
      INSTANCE = new LazyLoadManager(context.getApplicationContext()); 
     } 
     return INSTANCE; 
    } 

    private void loadData(final ViewHolder viewHolder, final Model myModel) { 

     // Put ViewHolder and respective tag into Map 
     viewHolders.put(viewHolder, myModel.getTag()); 

     final Handler handler = new Handler(new Handler.Callback() { 
      @Override 
      public boolean handleMessage(Message msg) { 

       // Get result object 
       Model myResultModel = (Model) msg.obj; 

       // Result was initialized 
       if (myResultModel != null) { 

        // Get ViewHolder tag from map 
        String tag = viewHolders.get(viewHolder); 

        // Set ViewHolder content, if saved tag matches tag of this ViewHolder 
        if (tag != null && tag.equals(viewHolder.getTag())) { 
         viewHolder.viewA.setText(myResultModel.getThis()); 
         viewHolder.viewB.setText(myResultModel.getThat()); 
        } 
       } 
       return true; 
      } 
     }); 

     pool.submit(new Runnable() { 
         @Override 
         public void run() { 
          Model myResultModel = null; 

          if (myModel != null) { 

           // do required calculations and secondary queries based on myModel 

           myResultModel.setThis(result1); 
           myResultModel.setThat(result2); 
          } 

          Message message = Message.obtain(); 
          message.obj = myResultModel; 

          handler.sendMessage(message); 
         } 
        } 

     ); 
    } 

Im onBindViewHolder Methode meiner RecyclerView ich meine LazyLoadManager dann nennen wie diese

LazyLoadManager.getInstance(context).loadData(viewHolder, myModel);