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".
- No se ha podido abrir la base de datos de georreferencias de vista web de Android
- SQLite en el operador en query ()
- Android: ¿ver bases de datos SQLite en el dispositivo?
- Android NDK construir de spatialite?
- cómo guardar datos de json en sqlite en android
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; } } }
- Cómo implementar SQLCipher cuando se utiliza SQLiteOpenHelper
- Problema con SQLiteOpenHelper en android 2.X y 3.X
- Android abrir o crear base de datos
- Cambiar el número de versión de la base de datos SQLite
- ActiveAndroid Relación de muchos a muchos
- Comprobación de consultas de Sqlite - menor y mayor que
- SQLiteOpenHelper - crear base de datos en tarjeta SD
- Cómo recuperar una imagen de SQLite DB?
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
- La vista de texto no se desplaza dentro de la lista personalizada
- android TextView.setText no funciona en widget simple