Cierre del cursor en onPostExecute no produce nada

Estoy utilizando AsyncTask para cargar datos de una base de datos SQLite y luego proporcionar datos a un Recycler View utilizando un StaggeredLayoutManager y CustomListAdapter.

Si no cierra el cursor del método doInBackground en onPostExecuteMethod, la transición de la actividad anterior es laggy, y androide logcat dice "Omitido 52 cuadros".

Si cierro el cursor, al final del método Post Execute, el retraso no se produce, pero no se procesa nada dentro de la actividad. (Recycler View no muestra nada).

@Override protected void onPostExecute(Void Void) { c.close(); swipeRefreshLayout.setRefreshing(false); swipeRefreshLayout.setOnRefreshListener( new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { new MyTask().execute(); } }); swipeRefreshLayout.setColorSchemeColors(getResources().getIntArray(R.array.swipeRefreshColors)); } 

método doInBackground

  try { myDb = new SavedData(getApplicationContext()); writeableDatabase = myDb.getReadableDatabase(); final String[] projection = {SavedData.COLUMN_NAME_ENTRY_ID, SavedData.COLUMN_NAME_PRICE, SavedData.COLUMN_NAME_SHIPPING, SavedData.COLUMN_NAME_WEIGHT, SavedData.COLUMN_NAME_PRODUCT}; sortOrder = BookSave.COLUMN_NAME_ENTRY_ID + " DESC"; c = writeableDatabase.query( SavedData.TABLE_NAME, projection, null, null, null, null, sortOrder ); m = new MyListCursorAdapter(getApplicationContext(), c); gaggeredGridLayoutManager = new StaggeredGridLayoutManager(NUM, 1); } catch (Exception e) { e.printStackTrace(); } finally { } 

La clase BaseAdapter

 import android.content.Context; import android.database.Cursor; import android.database.DataSetObserver; import android.support.v7.widget.RecyclerView; public abstract class CursorRecyclerViewAdapter<VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> { private Context mContext; private Cursor mCursor; private boolean mDataValid; private int mRowIdColumn; private DataSetObserver mDataSetObserver; public CursorRecyclerViewAdapter(Context context, Cursor cursor) { mContext = context; mCursor = cursor; mDataValid = cursor != null; mRowIdColumn = mDataValid ? mCursor.getColumnIndex("_id") : -1; mDataSetObserver = new NotifyingDataSetObserver(); if (mCursor != null) { mCursor.registerDataSetObserver(mDataSetObserver); } } public Cursor getCursor() { return mCursor; } @Override public int getItemCount() { if (mDataValid && mCursor != null) { return mCursor.getCount(); } return 0; } @Override public long getItemId(int position) { if (mDataValid && mCursor != null && mCursor.moveToPosition(position)) { return mCursor.getLong(mRowIdColumn); } return 0; } @Override public void setHasStableIds(boolean hasStableIds) { super.setHasStableIds(true); } public abstract void onBindViewHolder(VH viewHolder, Cursor cursor); @Override public void onBindViewHolder(VH viewHolder, int position) { if (!mDataValid) { throw new IllegalStateException("this should only be called when the cursor is valid"); } if (!mCursor.moveToPosition(position)) { throw new IllegalStateException("couldn't move cursor to position " + position); } onBindViewHolder(viewHolder, mCursor); } /** * Change the underlying cursor to a new cursor. If there is an existing cursor it will be * closed. */ public void changeCursor(Cursor cursor) { Cursor old = swapCursor(cursor); if (old != null) { old.close(); } } /** * Swap in a new Cursor, returning the old Cursor. Unlike * {@link #changeCursor(Cursor)}, the returned old Cursor is <em>not</em> * closed. */ public Cursor swapCursor(Cursor newCursor) { if (newCursor == mCursor) { return null; } final Cursor oldCursor = mCursor; if (oldCursor != null && mDataSetObserver != null) { oldCursor.unregisterDataSetObserver(mDataSetObserver); } mCursor = newCursor; if (mCursor != null) { if (mDataSetObserver != null) { mCursor.registerDataSetObserver(mDataSetObserver); } mRowIdColumn = newCursor.getColumnIndexOrThrow("_id"); mDataValid = true; notifyDataSetChanged(); } else { mRowIdColumn = -1; mDataValid = false; notifyDataSetChanged(); //There is no notifyDataSetInvalidated() method in RecyclerView.Adapter } return oldCursor; } private class NotifyingDataSetObserver extends DataSetObserver { @Override public void onChanged() { super.onChanged(); mDataValid = true; notifyDataSetChanged(); } @Override public void onInvalidated() { super.onInvalidated(); mDataValid = false; notifyDataSetChanged(); //There is no notifyDataSetInvalidated() method in RecyclerView.Adapter } } } 

La clase de adaptador ampliada

 import android.content.Context; import android.content.Intent; import android.content.res.Resources; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Typeface; import android.os.AsyncTask; import android.support.v7.widget.CardView; import android.support.v7.widget.RecyclerView; import android.util.DisplayMetrics; import android.util.Log; import android.view.Display; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.Button; import android.widget.LinearLayout; import android.widget.TextView; public class MyListCursorAdapter extends CursorRecyclerViewAdapter<MyListCursorAdapter.ViewHolder> { private static final String TAG = "MyListCursorAdapter"; public MyListCursorAdapter(Context context, Cursor cursor) { super(context, cursor); } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View itemView = LayoutInflater.from(parent.getContext()) .inflate(R.layout.productList, parent, false); ViewHolder vh = new ViewHolder(itemView); return vh; } @Override public void onBindViewHolder(final ViewHolder viewHolder, final Cursor cursor) { Book myListItem = Book.fromCursor(cursor); viewHolder.titleTextView.setText(myListItem.getTitle()); viewHolder.shippingTextView.setText(myListItem.getAShipping()); Log.d(TAG, "onBindViewHolder: "+viewHolder.isRecyclable()); } public static class ViewHolder extends RecyclerView.ViewHolder { public TextView shippingTextView; public TextView titleTextView; public LinearLayout insideCard; public Button payButton; public View seperator; public CardView cv; public View view; public ViewHolder(final View view) { super(view); WindowManager wm = (WindowManager) view.getContext().getSystemService(Context.WINDOW_SERVICE); Display display = wm.getDefaultDisplay(); DisplayMetrics DM = new DisplayMetrics(); display.getMetrics(DM); payButton = (Button) view.findViewById(R.id.readButton); seperator = view.findViewById(R.id.separator); titleTextView = (TextView) view.findViewById(R.id.titleTextView); insideCard = (LinearLayout) view.findViewById(R.id.insideCard); insideCard.getLayoutParams().width = (DM.widthPixels / 2) - 24; shippingTextView = (TextView) view.findViewById(R.id.shippingTextView); //typeface Typeface light = Typeface.createFromAsset(titleTextView.getResources().getAssets(), "fonts/light.ttf"); titleTextView.setTypeface(light); Typeface regular = Typeface.createFromAsset(authorTextView.getResources().getAssets(), "fonts/thinItalic.ttf"); shippingTextView.setTypeface(regular); payButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent goToCheckout = new Intent(view.getContext(), ShowReader.class); goToCheckout.putExtra("PRODUCT_NAME", titleTextView.getText()); view.getContext().startActivity(goToCheckout); } }); setWidth((DM.widthPixels / 2) - 24); } public void setWidth(int a) { a = a - 8 * 4; payButton.getLayoutParams().width = a; seperator.getLayoutParams().width = a; } } } 

Aquí está su problema:

 //typeface Typeface light = Typeface.createFromAsset(titleTextView.getResources().getAssets(), "fonts/light.ttf"); titleTextView.setTypeface(light); Typeface regular = Typeface.createFromAsset(authorTextView.getResources().getAssets(), "fonts/thinItalic.ttf"); shippingTextView.setTypeface(regular); 

cada vez que vaya a crear un nuevo ViewHolder que va a leer desde el archivo. Es una operación pesada cuando lo haces varias veces. Así que una solución es leer una sola vez y poner en caché las fuentes. Así que vamos a ver algunos códigos:

 public class MyFontProvider { private static final String TAG = MyFontProvider.class.getSimpleName(); private Map<String, Typeface> mCache; private static volatile MyFontProvider sInstance; public static MyFontProvider getInstance() { if (sInstance == null) { synchronized (MyFontProvider.class) { if (sInstance == null) { sInstance = new MyFontProvider(); } } } return sInstance; } private MyFontProvider() { mCache = new Hashtable<>(); } public synchronized Typeface getFont(String assetPath, Context context) { if (!mCache.containsKey(assetPath)) { try { Typeface t = Typeface.createFromAsset(context.getAssets(), assetPath); mCache.put(assetPath, t); } catch (Exception e) { Log.e(TAG, "Error getting typeface (" + assetPath + " ) " + e.getMessage()); return null; } } return mCache.get(assetPath); } } 

Ahora puedes cambiar

 //typeface Typeface light = Typeface.createFromAsset(titleTextView.getResources().getAssets(), "fonts/light.ttf"); titleTextView.setTypeface(light); Typeface regular = Typeface.createFromAsset(authorTextView.getResources().getAssets(), "fonts/thinItalic.ttf"); shippingTextView.setTypeface(regular); 

a

 //typeface titleTextView.setTypeface(MyFontProvider.getInstance().getFont("fonts/light.ttf",this)); shippingTextView.setTypeface(MyFontProvider.getInstance().getFont("fonts/thinItalic.ttf",this)); 

Y también es una buena idea para almacenar una ruta de la fuente como una public final static String para que pueda cambiarlo en un lugar y no tiene que modificar varios archivos.

No debe cerrar el cursor hasta que haya terminado completamente con él. Ha perdido su fuente de datos una vez que ha hecho eso, por lo que no ve nada después de cerrarlo.

¿Ya analizaste tu adaptador? Dado que usted tiene retraso cuando usted no cierra el cursor, pero ninguno con usted hace, hay siempre la posibilidad que usted no está siendo eficiente en crear sus opiniónes

  • Sqlite cómo obtener elementos de cadena con el cursor
  • IOS / Android sincronización con Delphi / C # aplicación de escritorio
  • ¿Cómo puedo restablecer un número de secuencia autoincrement en sqlite
  • Android Eclipse DDMS - No se puede extraer el archivo del dispositivo enraizado
  • ¿Se ha construido SQLite en Android con el tokenizador ICU habilitado para FTS?
  • Permiso de negación: esto requiere android.permission.INTERACT_ACROSS_USERS_FULL
  • La base de datos Sqlite onUpgrade () no se llama
  • ¿Dónde se almacena la base de datos SQLite en el emulador de Android?
  • Android: Fragmentos, SQLite y cargadores
  • Base de datos de SQLite Android eliminada después de desinstalar
  • Uso de la base de datos existente en Android Wear
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.