Ponieważ Hans Boehm w rozmowie Google I/O '17 "How to Manage Native C++ Memory in Android" sugeruje użycie klasy PhantomReference
w celu zapewnienia prawidłowego usunięcia natywnych urządzeń równorzędnych.Usuwanie rodzimych obiektów równorzędnych z ogólną klasą PhantomReference
W połączonym wideo pod numerem 18 min 57 sec pokazuje przykładową implementację obiektu rejestrującego się w klasie PhantomReference
dla jego typu. Ta klasa PhantomReference
pokazuje wtedy pod numerem 19 min 49 sec. Więc skopiowałem jego podejście do mojego przykładowego obiektu. Zobacz poniżej.
Chociaż to podejście działa dobrze, nie skaluje się. Będę musiał utworzyć całkiem sporo obiektów i nie znalazłem sposobu na utworzenie klasy bazowej (dla moich obiektów lub klasy bazowej PhantomReference
), która zajmowałaby dowolne obiekty i poprawnie obsługiwałaby natywne usuwanie.
Jak utworzyć podstawową klasę podstawową PhantomReference
, która może wywoływać natywną metodę statyczną na podanym obiekcie?
Próbowałem przekształcić generic PhantomReference
, ale natywna metoda usuwania statycznego przeszkadza w implementacji.
My WorkViewModel
import android.databinding.*;
public class WorkViewModel extends BaseObservable
{
private long _nativeHandle;
public WorkViewModel(Database database, int workId)
{
_nativeHandle = create(database.getNativeHandle(), workId);
WorkViewModelPhantomReference.register(this, _nativeHandle);
}
private static native long create(long databaseHandle, int workId);
static native void delete(long nativeHandle);
@Bindable
public native int getWorkId();
public native void setWorkId(int workId);
}
My WorkViewModelPhantomReference
import java.lang.ref.*;
import java.util.*;
public class WorkViewModelPhantomReference extends PhantomReference<WorkViewModel>
{
private static Set<WorkViewModelPhantomReference> phantomReferences = new HashSet<WorkViewModelPhantomReference>();
private static ReferenceQueue<WorkViewModel> garbageCollectedObjectsQueue = new ReferenceQueue<WorkViewModel>();
private long _nativeHandle;
private WorkViewModelPhantomReference(WorkViewModel workViewModel, long nativeHandle)
{
super(workViewModel, garbageCollectedObjectsQueue);
_nativeHandle = nativeHandle;
}
public static void register(WorkViewModel workViewModel, long nativeHandle)
{
phantomReferences.add(new WorkViewModelPhantomReference(workViewModel, nativeHandle));
}
public static void deleteOrphanedNativePeerObjects()
{
WorkViewModelPhantomReference reference;
while((reference = (WorkViewModelPhantomReference)garbageCollectedObjectsQueue.poll()) != null)
{
WorkViewModel.delete(reference._nativeHandle);
phantomReferences.remove(reference);
}
}
}
Wierzę, że od razu takie podejście nie jest skalowane. Ale nie rozumiem twojego drugiego problemu, który "nie znalazłeś sposobu na stworzenie klasy bazowej ... która zajmowałaby jakiekolwiek obiekty i poprawnie obsługiwałaby natywne usuwanie *". Masz działające rozwiązanie składające się z dwóch klas. Jaki problem powinna rozwiązać ta hipotetyczna klasa podstawowa? – Holger
@Holger dzięki za odpowiedź. Proszę wyjaśnić mi kwestię skali? To właśnie próbuję rozwiązać za pomocą hipotetycznej klasy bazowej. Mam wiele takich obiektów i dla każdego z nich muszę stworzyć drugą klasę widmową. Z klasą bazową chciałbym rozwiązać, że nie musiałbym tworzyć dodatkowej klasy lub uczynić ją tak prostą, że wystarczy tylko zdefiniować typ. –
Czekaj - tworzysz nową klasę fantomów dla każdego tworzonego obiektu? Albo co masz na myśli mówiąc "każdy z nich"? – Holger