I have a difficult problem to explain and that I can put code if you wish but I think it is better to comment as you can and give me opinion. I have an android application that works with several activities, but it contains a main one and in it I do change fragments to navigate ... A fragment menu that connects to an interface to pass a number (this number passes it to the activity and makes the change to x fragment) ... Menu with buttons on the left and dynamic fragment on the right. Ok, the app is already finished but I have found an error that has to do with changing fragments and closing cursors ... It is in a specific fragment where I use a custom listview to load content from an internal sqlite database. I make selects, therefore I open cursors, and I close them .. Everything is perfect. But I have another fragment with a recyclerview that takes a bit of load because it's like a gallery with photo thumbnails. ** These two fragments are conflicts. In the second I do not open cursors. Well, when I open the listview and return to the recyclerview, when I do this twice, I check out the application (and re-enter) and pull the typical error that you leave a cursor to close.
05-23 16:47:27.112 20877-20886/com.example.practicas_.arcadiatruck E/StrictMode: A resource was acquired at attached stack trace but never released. See java.io.Closeable for information on avoiding resource leaks.
java.lang.Throwable: Explicit termination method 'close' not called
at dalvik.system.CloseGuard.open(CloseGuard.java:180)
The point is that when I enter the listview fragment, I open it, and I can not close the cursor until I do something , or I can enter an item in the listview (load another list with more info) , and I close the previous cursor when I click) or change the fragment and when I change the fragment I use the aforementioned interface, and before making any fragment transaction, it ensures that if this cursor is open, close it. It closes it in all the other fragments, but in the recyclerview it takes a bit longer because at the end when I try several times, it has not closed correctly and gives the error. I tried using delay / handler to close the cursor before any fragment transaction and nothing was done. I'm desperate, it's a small error but since the client app is connected to the server, there are times when you restart the app and it does not connect well to the server. Well, in cases that it does not connect, it's because it does not reboot at all, but crashing, so to speak ...
Can you think of something I can do? I always close cursors, but when there is this type of delay between these two fragments in specific then at the end it finishes resetting the app ...
To close when I click on a menu button and access the interface, I use this code ... I put it to give you an idea how I do it, if with static variables it gives some kind of failure or something ... Within my fragment class, I use the normal cursor.close
...
if (HistoricoIntervenciones.cursor != null) {
if (!HistoricoIntervenciones.cursor.isClosed()) {
HistoricoIntervenciones.cursor.close();
}
}
A thousand thanks in advance.
* Updated 05/24/2018 * (Code of the class where I open the cursor, I also close it in another part that I put below, outside the class, in the menu when I play buttons and leave that fragment)
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.database.Cursor;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.RequiresApi;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;
/**
* A simple {@link Fragment} subclass.
*/
public class HistoricoIntervenciones extends Fragment {
public DataBaseManager manager;
public static SimpleCursorAdapter adapter;
Fragment fragmentInformacionHI;
public static Cursor cursor;
public HistoricoIntervenciones() {
// Required empty public constructor
}
@RequiresApi(api = Build.VERSION_CODES.M)
@Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_historico_intervenciones, container, false);
manager = new DataBaseManager(getContext());
fragmentInformacionHI = new InfoHI();
ListView lvData = view.findViewById(R.id.lvData);
String[] from = new String[]{DataBaseManager.CN_FECHA, DataBaseManager.CN_EXP, DataBaseManager.CN_P, DataBaseManager.CN_DIRECCION, DataBaseManager.CN_POBLACION, DataBaseManager.CN_TIPOLOGIA, DataBaseManager.CN_DESCRIPCION, DataBaseManager.CN_FECHA2, DataBaseManager.CN_COORDENADAX, DataBaseManager.CN_COORDENADAY, DataBaseManager.CN_ALERTANTE, DataBaseManager.CN_TELEFONO, DataBaseManager.CN_PROVINCIA};
int[] to = new int[]{R.id.fecha1, R.id.exp1, R.id.p1, R.id.direccion1, R.id.poblacion1, R.id.tipologia1, R.id.descripcion1, R.id.o_fecha2, R.id.o_coordenadax, R.id.o_coordenaday, R.id.o_alertante, R.id.o_telefono, R.id.o_provincia};
cursor = manager.cargarCursor();
adapter = new SimpleCursorAdapter(getContext(), R.layout.listview_item_row_lvhi, cursor, from, to, 0);
lvData.setAdapter(adapter);
lvData.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
FragmentManager miManejador = getFragmentManager();
TextView expediente = view.findViewById(R.id.exp1);
TextView prioridad = view.findViewById(R.id.p1);
TextView fecha = view.findViewById(R.id.o_fecha2);
TextView tipologia = view.findViewById(R.id.tipologia1);
TextView direccion = view.findViewById(R.id.direccion1);
TextView poblacion = view.findViewById(R.id.poblacion1);
TextView provincia = view.findViewById(R.id.o_provincia);
TextView coordenadax = view.findViewById(R.id.o_coordenadax);
TextView coordenaday = view.findViewById(R.id.o_coordenaday);
TextView descripcion = view.findViewById(R.id.descripcion1);
TextView alertante = view.findViewById(R.id.o_alertante);
TextView telefono = view.findViewById(R.id.o_telefono);
String info_expediente = expediente.getText().toString();
String info_prioridad = prioridad.getText().toString();
String info_fecha = fecha.getText().toString();
String info_tipologia = tipologia.getText().toString();
String info_direccion = direccion.getText().toString();
String info_poblacion = poblacion.getText().toString();
String info_provincia = provincia.getText().toString();
String info_coordenadax = coordenadax.getText().toString();
String info_coordenaday = coordenaday.getText().toString();
String info_descripcion = descripcion.getText().toString();
String info_alertante = alertante.getText().toString();
String info_telefono = telefono.getText().toString();
Bundle args = new Bundle();
args.putString("expediente", info_expediente);
args.putString("prioridad", info_prioridad);
args.putString("fecha2", info_fecha);
args.putString("tipologia", info_tipologia);
args.putString("direccion", info_direccion);
args.putString("poblacion", info_poblacion);
args.putString("provincia", info_provincia);
args.putString("coordenadax", info_coordenadax);
args.putString("coordenaday", info_coordenaday);
args.putString("descripcion", info_descripcion);
args.putString("alertante", info_alertante);
args.putString("telefono", info_telefono);
fragmentInformacionHI.setArguments(args);
FragmentTransaction miTransaccion = miManejador.beginTransaction();
miTransaccion.replace(R.id.actividadfragments, fragmentInformacionHI);
cursor.close();
miTransaccion.commit();
}
});
return view;
}
}
This is where I close the cursor again when I leave the fragment without pressing any item in the listview.
public class Menu extends Fragment {
private final int[] BOTONESMENU = {R.id.botoninicio, R.id.botonhistoricointervenciones, R.id.botonarchivos, R.id.botonconfiguracion, R.id.boton_emergencia};
public Menu() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View mimenu = inflater.inflate(R.layout.fragment_menu, container, false);
Button botonmenu;
for (int i = 0; i < BOTONESMENU.length; i++) {
botonmenu = (Button) mimenu.findViewById(BOTONESMENU[i]);
final int queBoton = i;
botonmenu.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (HistoricoIntervenciones.cursor != null) {
if (!HistoricoIntervenciones.cursor.isClosed()) {
HistoricoIntervenciones.cursor.close();
}
}
Activity estaActividad = getActivity();
((ComunicaMenu) estaActividad).menu(queBoton);
//Aquí le paso a la interfaz comunicamenu el boton que pulse, y con este botón inicia la transacción de fragmentos
}
});
}
return mimenu;
}
}