Erreur de mémoire de curseur curseur Android dans un fragment spécifique

J'ai une application Android qui utilise un service pour collecter les données du capteur toutes les 5 ms et l'insère dans une table sqlite. Dans une session typique, il y aura environ 40 minutes d'enregistrements. Tout ce code semble fonctionner correctement.

J'ai un problème étrange où si l'utilisateur navigue vers un fragment particulier, j'ai une CursorWindow: Window is full: requested allocation XXX erreur de l' CursorWindow: Window is full: requested allocation XXX . Je ne suis pas sûr de ce qui est spécial sur ce fragment spécifique qui cause cette erreur, et ne se produit que avec ce fragment

  • Comment masquer un EditText pour afficher le format de date dd / mm / aaaa
  • Afficher le marqueur à l'intérieur d'une ressource étirée qui a été obtenue à partir de l'URL
  • Comment obtenir l'échelle de webview dans Android 4
  • Impossible de recevoir une notification push dans Android en utilisant Parse
  • Studio Android 2.3 course instantanée ne fonctionne pas
  • Quels sont les outils: maquette, outils: mockup_crop et outils: mockup_opacity
  • Le fragment en question contient un bouton qui, lorsqu'il est cliqué, fera un certain nombre de choses:

    • Crée des répertoires sur le stockage externe
    • Copie toutes les données du capteur de la table temporaire et l'insère dans un tableau plus permanent
    • Crée une copie de l'intégralité .db fichier .db dans un stockage externe
    • Détermine le contenu d'une table et l'écrit dans un fichier CSV
    • Demande un autre tableau pour les données du capteur et écrit toutes ces données de capteur sur un autre fichier CSV
    • Utilise un scanner multimédia pour analyser tous les fichiers dans le répertoire d'exportation afin qu'ils puissent être consultés via MTP

    Le code du fragment ressemble à ceci (beaucoup de blocs de capture ont été laissés de côté pour la brièveté – ils ne sont généralement que des informations):

     public class SaveFragment extends Fragment implements View.OnClickListener { Button saveButton; MainActivity mainActivity; DBHelper dbHelper; Boolean subjectDataExists; MediaScanner mediaScanner; static ProgressDialog dialog; public SaveFragment() { // Required empty public constructor } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_save, container, false); //Get save button view saveButton = (Button) view.findViewById(R.id.saveButton); saveButton.setOnClickListener(this); //Get DBHelper dbHelper = DBHelper.getInstance(getActivity(), new DatabaseHandler()); //Check if sensor data has been recorded subjectDataExists = dbHelper.checkSubjectDataExists(Short.parseShort(dbHelper.getTempSubInfo("subNum"))); // Inflate the layout for this fragment return view; } @Override public void onClick(View v) { //Alert dialog for saving/quitting AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(mainActivity); if (subjectDataExists) { alertDialogBuilder.setTitle("Save and quit?"); alertDialogBuilder.setMessage("Are you sure you want to save the data and quit the current session?"); } else { alertDialogBuilder.setTitle("Quit?"); alertDialogBuilder.setMessage("Are you sure you want to quit the current session? \n\n No data will be saved."); } alertDialogBuilder.setPositiveButton("Yes", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { //Save if sensor data exists, otherwise quit if (subjectDataExists) { new ExportDatabaseCSVTask().execute(); } else { quitSession(); } } }); alertDialogBuilder.setNegativeButton("No", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }); AlertDialog quitAlertDialog = alertDialogBuilder.create(); quitAlertDialog.show(); } //Quit the current session and go back to login screen private void quitSession(){ Intent intent = new Intent(getActivity(), LoginActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(intent); getActivity().finishAffinity(); } //Message handler class for database progress updates private static class DatabaseHandler extends Handler { @Override public void handleMessage (Message msg){ Double progressPercent = (Double) msg.obj; Integer progressValue = 40 + (int) Math.ceil(progressPercent/2); dialog.setProgress(progressValue); } } //Async class for CSV export task public class ExportDatabaseCSVTask extends AsyncTask<String, Integer, Boolean> { @Override protected void onPreExecute() { //show a progress dialog } protected Boolean doInBackground(final String... args) { //Create directories for the output csv files String pathToExternalStorage = Environment.getExternalStorageDirectory().toString(); File exportDir = new File(pathToExternalStorage, "/Data"); File subjectDataDir = new File(exportDir, "/subjects"); publishProgress(5); //The sleep is here just so the progress updates in the dialog are visually slower SystemClock.sleep(100); if (!exportDir.exists()) { Boolean created = exportDir.mkdirs(); } publishProgress(10); SystemClock.sleep(100); if (!subjectDataDir.exists()) { Boolean created = subjectDataDir.mkdirs(); } publishProgress(15); SystemClock.sleep(100); //If all directories have been created successfully if (exportDir.exists() && subjectDataDir.exists()) { try { //Copy temp subject and sensor data to persistent db tables dbHelper.copyTempData(); publishProgress(20); SystemClock.sleep(200); //Backup the SQL DB file File data = Environment.getDataDirectory(); String currentDBPath = "//data//com.example.app//databases//" + DBHelper.DATABASE_NAME; File currentDB = new File(data, currentDBPath); File destDB = new File(exportDir, DBHelper.DATABASE_NAME); publishProgress(25); SystemClock.sleep(100); if (exportDir.canWrite()) { if (currentDB.exists()) { FileChannel src = new FileInputStream(currentDB).getChannel(); FileChannel dst = new FileOutputStream(destDB).getChannel(); dst.transferFrom(src, 0, src.size()); src.close(); dst.close(); } } publishProgress(35); SystemClock.sleep(300); //Export subjects table/tracking sheet File trackingSheet = new File(exportDir, "trackingSheet.csv"); try{ dbHelper.exportTrackingSheet(trackingSheet); } catch (SQLException | IOException e){ } publishProgress(40); SystemClock.sleep(300); //Export individual subject data String subNum = dbHelper.getTempSubInfo("subNum"); File subjectFile = new File(subjectDataDir, subNum + ".csv"); try{ dbHelper.exportSubjectData(subjectFile, subNum); } catch (SQLException | IOException e){ } publishProgress(90); SystemClock.sleep(300); //Scan all files for MTP List<String> fileList = getListFiles(exportDir); String[] allFiles = new String[fileList.size()]; allFiles = fileList.toArray(allFiles); mediaScanner = new MediaScanner(); try{ mediaScanner.scanFile(getContext(), allFiles, null, mainActivity.logger); } catch (Exception e) { } publishProgress(100); SystemClock.sleep(400); return true; } catch (SQLException | IOException e) { } else { //Directories don't exist if (!exportDir.exists()) { } else if (!subjectDataDir.exists()) { return false; } } public void onProgressUpdate(Integer ... progress){ dialog.setProgress(progress[0]); if (progress[0] == 100){ dialog.setMessage("Quitting..."); } } protected void onPostExecute(final Boolean success) { if (dialog.isShowing()) { dialog.dismiss(); } if (success) { //Restart app and go back to login screen quitSession(); } } //Recursive file lister for MTP private List<String> getListFiles(File parentDir) { ArrayList<String> inFiles = new ArrayList<>(); File[] files = parentDir.listFiles(); //Loop through everything in base directory, including folders for (File file : files) { if (file.isDirectory()) { //Recursively add files from subdirectories inFiles.addAll(getListFiles(file)); } else { inFiles.add(file.getAbsolutePath()); } } return inFiles; } } } 

    Une fois que beaucoup de données de capteur ont été enregistrées, j'obtiens l'erreur chaque fois que l'utilisateur navigue vers le fragment. Mais lorsque le bouton est cliqué, j'obtiens l'erreur en continu toutes les 2 secondes.

    Le code du service d'enregistrement des capteurs se trouve dans mon autre question: l' envoi d'un message par messagerie instantanée entre un fragment et un service

    Ce fragment appelle un certain nombre de méthodes de ma classe DBHelper (qui est configuré comme singleton):

     public class DBHelper extends SQLiteOpenHelper { SQLiteDatabase db; CSVWriter csvWrite; Cursor curCSV; static Handler messageHandler; private static DBHelper sInstance; public static synchronized DBHelper getInstance(Context context) { if (sInstance == null) { sInstance = new DBHelper(context.getApplicationContext()); Log.d(TAG, "New DBHelper created"); } return sInstance; } public static synchronized DBHelper getInstance(Context context, Handler handler) { if (sInstance == null) { sInstance = new DBHelper(context.getApplicationContext()); Log.d(TAG, "New DBHelper created"); } messageHandler = handler; return sInstance; } private DBHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); db = this.getWritableDatabase(); } public boolean checkSubjectDataExists(Short subNum) throws SQLException { //Check if sensor data, for this subject, exists in the temp data table String query = "SELECT * FROM " + DATA_TABLE_NAME_TEMP + " WHERE " + DATA_SUBJECT + "=" + subNum; Cursor c = db.rawQuery(query, null); boolean exists = (c.getCount() > 0); c.close(); return exists; } public void copyTempData() throws SQLException{ String copySubjectSQL = "INSERT INTO " + SUBJECTS_TABLE_NAME + " SELECT * FROM " + SUBJECTS_TABLE_NAME_TEMP; db.execSQL(copySubjectSQL); String copyDataSQL = "INSERT INTO " + DATA_TABLE_NAME + " SELECT * FROM " + DATA_TABLE_NAME_TEMP; db.execSQL(copyDataSQL); } public void exportTrackingSheet(File outputFile) throws SQLException, IOException { csvWrite = new CSVWriter(new FileWriter(outputFile)); curCSV = db.rawQuery("SELECT * FROM " + SUBJECTS_TABLE_NAME, null); csvWrite.writeNext(curCSV.getColumnNames()); while (curCSV.moveToNext()) { String arrStr[] = {curCSV.getString(0), curCSV.getString(1), curCSV.getString(2), curCSV.getString(3), curCSV.getString(4), curCSV.getString(5), curCSV.getString(6)}; csvWrite.writeNext(arrStr); } csvWrite.close(); curCSV.close(); } public void exportSubjectData(File outputFile, String subNum) throws IOException, SQLException { csvWrite = new CSVWriter(new FileWriter(outputFile)); curCSV = db.rawQuery("SELECT * FROM " + DATA_TABLE_NAME + " WHERE id = " + subNum, null); csvWrite.writeNext(curCSV.getColumnNames()); Integer writeCounter = 0; Integer numRows = curCSV.getCount(); while (curCSV.moveToNext()) { writeCounter++; String arrStr[] = {curCSV.getString(0), curCSV.getString(1), curCSV.getString(2), curCSV.getString(3), curCSV.getString(4), curCSV.getString(5), curCSV.getString(6), curCSV.getString(7), curCSV.getString(8), curCSV.getString(9), curCSV.getString(10), curCSV.getString(11), curCSV.getString(12), curCSV.getString(13), curCSV.getString(14), curCSV.getString(15), curCSV.getString(16), curCSV.getString(17), curCSV.getString(18), curCSV.getString(19), curCSV.getString(20), curCSV.getString(21), curCSV.getString(22), curCSV.getString(23), curCSV.getString(24), curCSV.getString(25)}; csvWrite.writeNext(arrStr); if ((writeCounter % 1000) == 0){ csvWrite.flush(); } Double progressPercent = Math.ceil(((float) writeCounter / (float) numRows)*100); Message msg = Message.obtain(); msg.obj = progressPercent; msg.setTarget(messageHandler); msg.sendToTarget(); } csvWrite.close(); curCSV.close(); } } 

    Le DBHelper et toutes les connexions SQL sont fermées onDestroy de mon activité principale

    Ma classe de scanner multimédia est également très simple:

     public class MediaScanner { protected void scanFile(final Context context, String[] files, String[] mimeTypes, final Logger logger) { MediaScannerConnection.scanFile(context, files, mimeTypes, new MediaScannerConnection.OnScanCompletedListener() { @Override public void onScanCompleted(String path, Uri uri) { //Log some info } } ); } } 

    Quelqu'un peut-il voir quelque chose de spécial sur mon code de fragment qui cause cette erreur de fenêtre de curseur?

  • Existe-t-il un moyen de revenir à Typeface.SERIF dans StaticLayout?
  • Manipulation de plusieurs géo-phases de transition avec zone commune
  • Comment vérifier la connectivité Internet au sein du réseau en version Android (en utilisant Internet d'un autre appareil via HOTSPOT)
  • Comment programmer la liste des utilisateurs enregistrés dans Firebase
  • Défilement horizontal dans gridview android
  • Découpez l'écran du téléphone sur deux parties qui font simultanément deux choses
  • coAndroid est un fan Android de Google, tout sur les téléphones Android, Android Wear, Android Dev et Android Games Apps.