Kotlin ile SQLite Kullanımı

SQLite telefonumuzda kullandığımız uygulama ile ilgili büyük çaplı verilerin depolanması için kullanılan bir veritabanıdır. Telefonumuzda kullandığımız uygulamayı sildiğimiz zaman otomatik bir şekilde tutulan verilerde silinir. Konunun daha iyi anlaşılması için basit bir program yaparak anlamaya çalışalım. Uygulamamızda filmlerin resimleri, isimleri, tarihleri ve imdb puanlarının tutulduğu bir liste yapmaya çalışacağız.
Yukarda uygulamanın nasıl çalıştığını gösteren bir gif bulunmaktadır. Uygulamanın nasıl çalıştığını anladığımıza göre adım adım yapmaya başlayalım.
Öncelikle uygulamamızda anlam karmaşasını önlemek için bir tane java sınıfı bir tane xml dosyası üzerinde gerçekleştireceğim ve visible-invisible özelliğini kullanarak geçiş yapacağım. Tasarım kısmı olan activity_main.xml dosyamızı aşağıdaki gibi düzenliyoruz.
activity_main.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.esatgozcu.kotlinsqlite.MainActivity"> <ListView android:id="@+id/listView" android:layout_width="match_parent" android:layout_height="match_parent" /> <android.support.constraint.ConstraintLayout android:id="@+id/secondLayout" android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="invisible"> <Button android:id="@+id/backButton" android:layout_width="50dp" android:layout_height="30dp" android:background="@android:drawable/ic_menu_revert" android:onClick="back" /> <ImageView android:id="@+id/imageView" android:layout_width="250dp" android:layout_height="200dp" android:layout_marginTop="48dp" android:onClick="select" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:srcCompat="@drawable/add_image" /> <EditText android:id="@+id/movieName" android:layout_width="200dp" android:layout_height="45dp" android:layout_marginTop="16dp" android:ems="10" android:hint="Flim Adını Giriniz" android:inputType="textPersonName" app:layout_constraintEnd_toEndOf="@+id/imageView" app:layout_constraintStart_toStartOf="@+id/imageView" app:layout_constraintTop_toBottomOf="@+id/imageView" /> <EditText android:id="@+id/movieYear" android:layout_width="200dp" android:layout_height="45dp" android:layout_marginTop="16dp" android:ems="10" android:hint="Flim Yılını Giriniz" android:inputType="textPersonName" app:layout_constraintEnd_toEndOf="@+id/imageView" app:layout_constraintStart_toStartOf="@+id/imageView" app:layout_constraintTop_toBottomOf="@+id/movieName" /> <EditText android:id="@+id/movieImdb" android:layout_width="200dp" android:layout_height="45dp" android:layout_marginTop="16dp" android:ems="10" android:hint="Flim Puanını Giriniz" android:inputType="textPersonName" app:layout_constraintEnd_toEndOf="@+id/imageView" app:layout_constraintStart_toStartOf="@+id/imageView" app:layout_constraintTop_toBottomOf="@+id/movieYear" /> <Button android:id="@+id/addButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="16dp" android:layout_marginTop="16dp" android:onClick="save" android:text="EKLE" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toBottomOf="@+id/movieImdb" app:layout_constraintVertical_bias="0.0" /> </android.support.constraint.ConstraintLayout> </android.support.constraint.ConstraintLayout> |
Flim eklerken sağ üst köşede bulunan üç noktaya tıkladığımızda ortaya çıkan menüyü nasıl yapacağımıza bakalım.
Öncelikle res klasörünün üstüne sağ tıklayarak new >> Directory diyerek menu adında bir klasör oluşturuyoruz. Daha sonra oluşturduğumuz menu klasörünün üstüne sağ tıklayarak new >> Menuresource file diyerek yeni xml dosyası oluşturuyoruz. Oluşturduğumuz xml dosyasını aşağıdaki gibi düzenliyoruz.
add_movie.xml
1 2 3 4 5 6 |
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id = "@+id/add_movie" android:title = "Flim Ekle"></item> </menu> |
Şimdi oluşturduğumuz menu xml dosyasını java dosyasına bağlamak için iki tane methodu MainActivity.kt dosyamıza override etmemiz gerekiyor.
MainActivity.kt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
@Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater menuInflater = getMenuInflater(); menuInflater.inflate(R.menu.add_movie, menu); return super.onCreateOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == R.id.add_movie) { // Menüden Flim Ekle Butonu seçilirse layout visible olacak. secondLayout = (ConstraintLayout)findViewById(R.id.secondLayout); // Verileri sıfırlıyoruz nameEdit.setText(""); yearEdit.setText(""); imdbEdit.setText(""); Bitmap background = BitmapFactory.decodeResource(getApplicationContext().getResources(), R.drawable.add_image); imageView.setImageBitmap(background); secondLayout.setVisibility(View.VISIBLE); listView.setVisibility(View.INVISIBLE); } return super.onOptionsItemSelected(item); } |
Buraya kadar tasarım kısmını ve menümüzü oluşturduk geriye işin asıl kısmı olan tasarıma anlam verecek olan kısmın anlatımına geçelim. Gerekli açıklamalar kod satırları arasında yapılmıştır.
MainActivity.kt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 |
package com.example.esatgozcu.kotlinsqlite import android.app.Activity import android.content.Context import android.content.Intent import android.content.pm.PackageManager import android.graphics.Bitmap import android.graphics.BitmapFactory import android.support.v7.app.AppCompatActivity import android.os.Bundle import android.provider.MediaStore import android.support.constraint.ConstraintLayout import android.view.Menu import android.view.MenuItem import android.view.View import android.widget.AdapterView import android.widget.ArrayAdapter import android.widget.ListView import kotlinx.android.synthetic.main.activity_main.* import java.io.ByteArrayOutputStream import java.util.jar.Manifest class MainActivity : AppCompatActivity() { var selectedImage : Bitmap? = null override fun onCreateOptionsMenu(menu: Menu?): Boolean { // menuInflater oluşturup menümüzle bağlıyoruz. val menuInflater = menuInflater menuInflater.inflate(R.menu.add_movie,menu) return super.onCreateOptionsMenu(menu) } // Menüden herhangi bir elemana tıkladığımızda override fun onOptionsItemSelected(item: MenuItem?): Boolean { // Menüden film ekleye tıkladığımızda.. if (item?.itemId == R.id.add_movie) { // Verileri sıfırlıyoruz movieName.setText("") movieYear.setText("") movieImdb.setText("") // Arka plan resmini sıfırlıyoruz val background = BitmapFactory.decodeResource(getApplicationContext().getResources(), R.drawable.add_image); imageView.setImageBitmap(background) secondLayout.setVisibility(View.VISIBLE); listView.setVisibility(View.INVISIBLE); } return super.onOptionsItemSelected(item) } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) getData() } fun getData() { // Verilerimiz için ArrayListlerimizi oluşturuyoruz. val movieNameArray = ArrayList<String>() val movieYearArray = ArrayList<String>() val movieImdbArray = ArrayList<String>() val movieImageArray = ArrayList<Bitmap>() // ArrayListleri listView'e aktarmak için adapter oluşturuyoruz val arrayAdapter = ArrayAdapter(this,android.R.layout.simple_list_item_1,movieNameArray) // ListView ile adapteri bağlıyoruz listView.adapter = arrayAdapter try { /* Verilerimizi veritabanından çekip arraylistlere aktarıyoruz */ // Movies isminde yeni veritabanı oluşturuyoruz. val database = this.openOrCreateDatabase("Movies", Context.MODE_PRIVATE,null) // Veritabanımızın için movies isimli tablomuzu oluturuyoruz. database.execSQL("CREATE TABLE IF NOT EXISTS movies (name VARCHAR,year VARCHAR,imdb VARCHAR,image BLOB)") // Bütün verileri çekiyoruz ve cursor nesnesine aktarıyoruz index numarasına göre verileri tekrardan çekeceğiz val cursor = database.rawQuery("SELECT * FROM movies",null) // Verileri çekebilmek için index numaralarını alıyoruz. val nameIx = cursor.getColumnIndex("name") val yearIx = cursor.getColumnIndex("year") val imdbIx = cursor.getColumnIndex("imdb") val imageIx = cursor.getColumnIndex("image") // Satır başına gidiyoruz. cursor.moveToFirst() while (cursor!=null) { // cursor nesnesi boş değilse verilerimizi ArrayListlere aktarıyoruz. movieNameArray.add(cursor.getString(nameIx)) movieYearArray.add(cursor.getString(yearIx)) movieImdbArray.add(cursor.getString(imdbIx)) // Resimleri ekliyoruz. val byteArray = cursor.getBlob(imageIx) val image = BitmapFactory.decodeByteArray(byteArray,0,byteArray.size) movieImageArray.add(image) // Bir sonraki satıra geçiyoruz. cursor.moveToNext() // ArrayAdaptere değişiklik olduğunu bildiriyoruz. arrayAdapter.notifyDataSetChanged() } cursor?.close() }catch (e:Exception) { // Herhangi bir hata ile karşılaşıldığı zaman hatayı bastırıyoruz. e.printStackTrace() } // ListView'den herhangi bir item seçildiği zaman.. listView.onItemClickListener = AdapterView.OnItemClickListener { adapterView, view, position, id -> // Seçilen filmin verilerini aktarıyoruz. movieName.setText(movieNameArray.get(position)) movieYear.setText(movieYearArray.get(position)) movieImdb.setText(movieImdbArray.get(position)) imageView.setImageBitmap(movieImageArray.get(position)) listView.setVisibility(View.INVISIBLE) secondLayout.setVisibility(View.VISIBLE) } } // ImageView üstüne tıklanıp resim seçilmek istendiğinde.. fun select(view:View) { // Gerekli izinleri alınıp alınmadığını kontrol ediyoruz. if (checkSelfPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { // İzin alınmamış ise requestPermissions(arrayOf(android.Manifest.permission.READ_EXTERNAL_STORAGE),2) } else { // İzin alındı ise resim galerisine gidiyoruz val intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI) startActivityForResult(intent,1) } } override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) { if(requestCode==2) { // İzin sonucunda izin verilip verilmediğini tekrardan kontrol ediyoruz if (grantResults.size >0 && grantResults[0]==PackageManager.PERMISSION_GRANTED){ val intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI) startActivityForResult(intent,1) } } super.onRequestPermissionsResult(requestCode, permissions, grantResults) } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { // Resim galerisinden resim seçildi ise ve data boş değil ise ... if (requestCode ==1 && resultCode == Activity.RESULT_OK && data!=null) { val image = data.data try { // Seçilen resimi ImageView'e aktarıyoruz selectedImage = MediaStore.Images.Media.getBitmap(this.contentResolver,image) imageView.setImageBitmap(selectedImage) }catch (e:Exception) { e.printStackTrace() } } super.onActivityResult(requestCode, resultCode, data) } fun save (view: View) { val valMovieName = movieName.text.toString() val valMovieYear= movieYear.text.toString() val valMovieImdb = movieImdb.text.toString() val outputStream = ByteArrayOutputStream() selectedImage?.compress(Bitmap.CompressFormat.PNG,50,outputStream) val byteArray = outputStream.toByteArray() try { // Movies isminde yeni veritabanı oluşturuyoruz. val database = this.openOrCreateDatabase("Movies", Context.MODE_PRIVATE,null) // Veritabanımızın için movies isimli tablomuzu oluturuyoruz. database.execSQL("CREATE TABLE IF NOT EXISTS movies (name VARCHAR,year VARCHAR,imdb VARCHAR,image BLOB)") // Sql sorgumuzu hazırlıyoruz val sqlString = "INSERT INTO movies (name,year,imdb,image) VALUES (?, ?, ?, ?)" val statement = database.compileStatement(sqlString) // Verilerimizi ekliyoruz statement.bindString(1,valMovieName) statement.bindString(2,valMovieYear) statement.bindString(3,valMovieImdb) statement.bindBlob(4,byteArray) statement.execute() // Eklenilen verilerin güncellenmesi için getData fonksiyonunu tekrar çağırıyoruz. getData() } catch (e: Exception) { e.printStackTrace() } listView.setVisibility(View.VISIBLE) secondLayout.setVisibility(View.INVISIBLE) } fun back (view: View) { listView.setVisibility(View.VISIBLE) secondLayout.setVisibility(View.INVISIBLE) } } |
Böylelikle Android Studio ile nasıl veritabanı işlemlerini yapabileceğimizi görmüş olduk.
Projenin kaynak kodlarına buraya tıklayarak indirebilirsiniz.