Menggunakan kelas Aplikasi Android untuk menyimpan data

112

Saya sedang mengerjakan aplikasi Android yang cukup kompleks yang membutuhkan sejumlah besar data tentang aplikasi (saya akan mengatakan total sekitar 500KB - apakah ini besar untuk perangkat seluler?). Dari apa yang saya dapat katakan, setiap perubahan orientasi dalam aplikasi (dalam aktivitas, lebih tepatnya) menyebabkan kehancuran total dan rekreasi aktivitas. Berdasarkan temuan saya, kelas Aplikasi tidak memiliki siklus hidup yang sama (yaitu, untuk semua maksud dan tujuan, selalu dipakai). Apakah masuk akal untuk menyimpan informasi status di dalam kelas aplikasi dan kemudian mereferensikannya dari Aktivitas, atau apakah itu secara umum bukan metode yang "dapat diterima" karena batasan memori pada perangkat seluler? Saya sangat menghargai saran apa pun tentang topik ini. Terima kasih!

Dave
sumber
8
Ingatlah bahwa data dalam Aplikasi Anda masih dapat dihapus jika aplikasi Anda beralih ke latar belakang, jadi ini bukan solusi untuk menyimpan data yang selalu ingin Anda dapatkan kembali. Ini hanya berfungsi sebagai metode untuk tidak perlu membuat ulang objek mahal sesering mungkin.
Cheryl Simon
2
Mayra; Menurut saya aplikasi tersebut tidak "biasanya" dihapus (meskipun, seperti yang ditunjukkan seseorang nanti di utas ini, aplikasi "bisa"). Saya mungkin akan menggunakan beberapa jenis pendekatan "hybrid" dalam menggunakan aplikasi untuk menyimpan dan memuat data, tetapi kemudian menggunakan atribut "android: orientasi" pada aktivitas dalam file manifes untuk menimpa perilaku normal meruntuhkan dan membangun kembali aktivitas. Semua ini, tentu saja, mengasumsikan bahwa aplikasi dapat menentukan "kapan" dimusnahkan sehingga data dapat dipertahankan.
Dave

Jawaban:

134

Saya tidak berpikir 500kb akan menjadi masalah besar.

Apa yang Anda jelaskan persis bagaimana saya menangani masalah kehilangan data dalam suatu aktivitas. Saya membuat singleton global di kelas Aplikasi dan dapat mengaksesnya dari aktivitas yang saya gunakan.

Anda dapat menyebarkan data di dalam Global Singleton jika itu akan sering digunakan.

public class YourApplication extends Application 
{     
     public SomeDataClass data = new SomeDataClass();
}

Kemudian panggil dalam aktivitas apa pun dengan:

YourApplication appState = ((YourApplication)this.getApplication());
appState.data.UseAGetterOrSetterHere(); // Do whatever you need to with the data here.

Saya membahasnya di sini di posting blog saya , di bawah bagian "Global Singleton."

Bryan Denny
sumber
1
Sayangnya postingan blog yang dipermasalahkan tidak lagi tersedia di alamat itu.
mikebabcock
1
Saya telah memindahkan banyak hal di situs saya. Sampai diperbaiki, Anda dapat menemukannya di archive.org di sini: web.archive.org/web/20130818035631/http://www.bryandenny.com/…
Bryan Denny
1
saya tahu ini adalah posting lama tetapi saya baru saja menemukan masalah yang mungkin bisa diselesaikan, namun kelas ini perlu dideklarasikan di manifes entah bagaimana, bukan? saya tidak dapat mengakses kelas jadi merasa seperti inilah yang saya lewatkan ...
Ziv Kesten
1
@ZivKesten Bagaimana jika menambahkan atribut name = ke tag aplikasi di dalam manifes?
MikeC
@mgc terima kasih sudah lama, dan ya begitulah akhirnya saya berhasil, juga saya membuat instance dari kelas itu di mana pun saya butuhkan dengan memberikannya getApplicationContext () dengan cast ke kelas ini
Ziv Kesten
57

Mereka yang mengandalkan Applicationcontoh salah. Pada awalnya, ini mungkin tampak seolah-olah Applicationada selama seluruh proses aplikasi ada, tetapi ini adalah asumsi yang salah.

OS dapat menghentikan proses jika diperlukan. Semua proses dibagi menjadi 5 tingkat "killability" yang ditentukan dalam dokumen .

Jadi, misalnya, jika aplikasi Anda berjalan di latar belakang karena pengguna menjawab panggilan masuk, maka bergantung pada status RAM, OS mungkin (atau mungkin tidak) menghentikan proses Anda (menghancurkan Applicationinstance dalam proses) .

Saya pikir pendekatan yang lebih baik adalah mempertahankan data Anda ke file penyimpanan internal dan kemudian membacanya ketika aktivitas Anda dilanjutkan.

MEMPERBARUI:

Saya mendapat banyak tanggapan negatif, jadi sekarang saatnya menambahkan klarifikasi. :) Yah, awalnya saya benar-benar menggunakan asumsi yang salah bahwa status sangat penting untuk aplikasi. Namun jika aplikasi Anda baik-baik saja dan terkadang statusnya hilang (bisa jadi beberapa gambar yang baru saja dibaca ulang / diunduh ulang), maka Anda dapat menyimpannya sebagai anggota Application.

Vit Khudenko
sumber
14
Jika Aplikasinya mati, lalu siapa yang peduli, bukan? Aplikasi hilang. Seperti yang saya pahami, Android akan mengklaim kembali proses yang berisi memori seperti Aktivitas. Jika proses yang berisi Aplikasi dimatikan (apakah Android akan melakukannya?), Itu pada dasarnya seperti mematikan aplikasi. Pengguna perlu meluncurkan aplikasi lagi dan, pada saat itu, siapa yang peduli? Ini adalah contoh aplikasi baru.
Andrew
14
Ini adalah kejutan yang tidak menyenangkan bagi kami dalam produksi. Percayalah Android membunuh proses, itu hanya bergantung pada status RAM dan faktor lain yang dijelaskan dalam dokumentasi. Itu adalah mimpi buruk bagi kami jadi saya hanya berbagi pengalaman nyata saya. Kami tidak memiliki ini di emulator, tetapi di dunia nyata beberapa perangkat 'kelebihan beban' dengan aplikasi, jadi mematikan proses latar belakang adalah situasi normal. Ya, jika pengguna kemudian memutuskan untuk mengangkat aplikasi ke latar depan - OS memulihkan tumpukannya termasuk Applicationinstance, namun tidak akan ada data statis yang Anda andalkan kecuali Anda mempertahankannya.
Vit Khudenko
2
Saya pikir saya mungkin akan menggunakan pendekatan hybrid. Saya sudah tahu tentang trik nyata untuk menimpa perubahan orientasi (yang memiliki manfaat lain). Karena aplikasinya adalah game, saya tidak yakin menyimpan data di antara peluncuran cukup "penting"; meskipun mungkin tidak akan terlalu sulit karena sebagian besar data dapat diserialkan (meskipun saya tidak ingin membuat serial dan menghapus serial antara setiap perubahan orientasi). Saya sangat menghargai masukannya. Saya tidak akan mengatakan bahwa mereka yang bergantung pada instance Aplikasi "salah". Banyak tergantung pada aplikasinya :).
Dave
1
@Arhimed Anda terlalu menggeneralisasi jawaban Anda. Dan menyarankan pendekatan sempit berdasarkan asumsi Anda. Asumsi Salah: Data yang disimpan dalam variabel statis perlu dipertahankan di seluruh sesi aplikasi. Mungkin ada banyak kasus penggunaan yang datanya sepele dan tidak perlu disimpan segera.
Mandar Limaye
2
Saya memiliki sekitar 1mb data dengan struktur yang rumit. Serialisasi / deserialisasi dapat menghabiskan biaya hingga 2-3 detik ketika perangkat kelebihan beban dengan pekerjaan. Ide untuk menyimpan / memuat di antara aktivitas menghabiskan terlalu banyak waktu. Saya menggunakan aplikasi sebagai penyimpanan. Tentu saja kelas data saya yang disimpan dalam instance aplikasi telah memeriksa setiap metode - apakah data masih hidup atau harus dimuat. Jadi Dave harus: 1. menyediakan load / save finctions 2. menyimpan data di aplikasi. 3. Tiga logika cek untuk mengakses data.
Kostadin
6

Jika Anda ingin mengakses "Global Singleton" di luar suatu aktivitas dan Anda tidak ingin melewati Contextsemua objek yang terlibat untuk mendapatkan singleton, Anda bisa menentukan atribut statis di kelas aplikasi Anda, yang menyimpan referensi ke diri. Inisialisasi saja atribut dalam onCreate()metode.

Sebagai contoh:

public class ApplicationController extends Application {
    private static ApplicationController _appCtrl;

    public static ApplicationController getAppCtrl()
    {
         return _appCtrl;
    }
}

Karena subkelas dari Applicationjuga bisa mendapatkan Sumber Daya, Anda bisa mengaksesnya hanya saat Anda mendefinisikan metode statis, yang mengembalikannya, seperti:

public static Resources getAppResources()
{
    return _appCtrl.getResources();
}

Namun berhati-hatilah saat membagikan referensi Konteks untuk menghindari kebocoran memori .

saksofon
sumber
6
Anda lupa mencatat bahwa Anda harus menambahkan atribut xml android: name = ". ApplicationController" tag aplikasi dalam manifes Anda untuk kelas yang akan dibuat.
eggie5
Anda sebenarnya tidak perlu memperpanjang Applicationuntuk melakukan ini. Anda dapat mendeklarasikan variabel anggota statis di kelas mana pun untuk melakukan ini.
David Wasser
2

Dave, jenis data apa itu? Jika itu adalah data umum yang berkaitan dengan aplikasi secara keseluruhan (contoh: data pengguna), maka perluas kelas Aplikasi dan simpan di sana. Jika data berkaitan dengan Aktivitas, Anda harus menggunakan penangan onSaveInstanceState dan onRestoreInstanceState untuk mempertahankan data pada rotasi layar.

Andrew
sumber
Bagaimana jika data sangat besar untuk disimpan di Parcel? Ini yang saya dapatkan: android.os.TransactionTooLargeException: data parcel size 838396 bytes
Arjun Issar
1

Anda sebenarnya dapat mengganti fungsionalitas orientasi untuk memastikan bahwa aktivitas Anda tidak dimusnahkan dan dibuat ulang. Lihat di sini .

Grantland Chew
sumber
16
Anda bisa melakukan banyak hal. Itu tidak berarti mereka adalah ide yang bagus. Ini bukan ide yang bagus.
Andrew
Menguji dengan mengubah orientasi layar adalah cara termudah untuk memastikan aplikasi Anda melakukan apa yang diasumsikan oleh Android.
18446744073709551615
0

Anda dapat membuat kelas Aplikasi dan menyimpan semua data Anda di panggilan itu untuk digunakan di mana saja dalam aplikasi Anda.

Ashish Jaiswal
sumber
0

Saya tahu ini adalah pertanyaan yang sangat lama tetapi menggunakan ViewModel dari komponen jetpack adalah cara terbaik untuk menjaga data antara rotasi Aktivitas.

Kelas ViewModel dirancang untuk menyimpan dan mengelola data terkait UI dengan cara sadar siklus hidup. Kelas ViewModel memungkinkan data bertahan dari perubahan konfigurasi seperti rotasi layar.

Dharmendra
sumber