《移动项目实践》实验报告——Android数据存储
生活随笔
收集整理的這篇文章主要介紹了
《移动项目实践》实验报告——Android数据存储
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
實驗目的
1、熟悉Android五種主要存儲方式的用法,包括共享參數SharedPreferences、數據庫SQLite、SD卡文件、App的全局內存;
2、熟悉重要組件之一的應用Application的基本概念與常見用法,以及四大組件之一的內容提供器ContentProvider的基本概念與常見用法;
實驗內容
“購物車”的設計與實現(參考效果圖)
初始效果
手機商場的商品列表
商品詳情頁面
添加商品后的購物車
實驗過程(實驗的設計思路、關鍵源代碼等)
源代碼:https://gitee.com/shentuzhigang/mini-project/tree/master/android-shopping
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#ffffdd"android:orientation="vertical" ><include layout="@layout/activity_shopping_title" /><ScrollViewandroid:layout_width="match_parent"android:layout_height="wrap_content" ><FrameLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:padding="5dp" ><LinearLayoutandroid:id="@+id/ll_content"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"android:visibility="gone" ><LinearLayoutandroid:id="@+id/ll_cart"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical" ></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"android:padding="10dp" ><TextViewandroid:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:gravity="center|right"android:text="總金額:"android:textColor="@color/black"android:textSize="17sp" /><TextViewandroid:id="@+id/tv_total_price"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="2"android:gravity="center|left"android:textColor="@color/red"android:textSize="25sp" /><Buttonandroid:id="@+id/btn_settle"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:gravity="center"android:text="結算"android:textColor="@color/black"android:textSize="20sp" /></LinearLayout></LinearLayout><LinearLayoutandroid:id="@+id/ll_empty"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"android:visibility="gone" ><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginBottom="100dp"android:layout_marginTop="100dp"android:gravity="center"android:text="哎呀,購物車空空如也,快去選購商品吧"android:textColor="@color/black"android:textSize="17sp" /><Buttonandroid:id="@+id/btn_shopping_channel"android:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center"android:text="逛逛手機商場"android:textColor="@color/black"android:textSize="17sp" /></LinearLayout></FrameLayout></ScrollView></LinearLayout> package io.shentuzhigang.demo.shoppingimport android.annotation.SuppressLint import android.app.Activity import android.app.AlertDialog import android.content.Intent import android.graphics.BitmapFactory import android.graphics.Color import android.os.Bundle import android.os.Environment import android.util.Log import android.util.TypedValue import android.view.* import android.view.ContextMenu.ContextMenuInfo import android.widget.ImageView import android.widget.ImageView.ScaleType import android.widget.LinearLayout import android.widget.TextView import android.widget.Toast import io.shentuzhigang.demo.shopping.MainApplication import io.shentuzhigang.demo.shopping.bean.CartInfo import io.shentuzhigang.demo.shopping.bean.GoodsInfo import io.shentuzhigang.demo.shopping.database.CartDBHelper import io.shentuzhigang.demo.shopping.database.GoodsDBHelper import io.shentuzhigang.demo.shopping.util.FileUtil import io.shentuzhigang.demo.shopping.util.SharedUtil import java.util.*/*** Created by ouyangshen on 2017/10/1.*/ @SuppressLint("SetTextI18n") class ShoppingCartActivity : Activity(), View.OnClickListener {private lateinit var iv_menu: ImageViewprivate lateinit var tv_count: TextViewprivate lateinit var tv_total_price: TextViewprivate lateinit var ll_content: LinearLayoutprivate lateinit var ll_cart: LinearLayoutprivate lateinit var ll_empty: LinearLayoutprivate var mCount // 購物車中的商品數量= 0private var mGoodsHelper // 聲明一個商品數據庫的幫助器對象: GoodsDBHelper? = nullprivate var mCartHelper // 聲明一個購物車數據庫的幫助器對象: CartDBHelper? = nulloverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)requestWindowFeature(Window.FEATURE_NO_TITLE)setContentView(R.layout.activity_shopping_cart)iv_menu = findViewById(R.id.iv_menu)val tv_title = findViewById<TextView>(R.id.tv_title)tv_count = findViewById(R.id.tv_count)tv_total_price = findViewById(R.id.tv_total_price)ll_content = findViewById(R.id.ll_content)ll_cart = findViewById(R.id.ll_cart)ll_empty = findViewById(R.id.ll_empty)iv_menu.setOnClickListener(this)findViewById<View>(R.id.btn_shopping_channel).setOnClickListener(this)findViewById<View>(R.id.btn_settle).setOnClickListener(this)iv_menu.setVisibility(View.VISIBLE)tv_title.text = "購物車"}// 顯示購物車圖標中的商品數量private fun showCount(count: Int) {mCount = counttv_count!!.text = "" + mCountif (mCount == 0) {ll_content!!.visibility = View.GONEll_cart!!.removeAllViews()ll_empty!!.visibility = View.VISIBLE} else {ll_content!!.visibility = View.VISIBLEll_empty!!.visibility = View.GONE}}override fun onClick(v: View) {if (v.id == R.id.iv_menu) { // 點擊了菜單圖標openOptionsMenu()} else if (v.id == R.id.btn_shopping_channel) { // 點擊了“商場”按鈕// 跳轉到手機商場頁面val intent = Intent(this, ShoppingChannelActivity::class.java)startActivity(intent)} else if (v.id == R.id.btn_settle) { // 點擊了“結算”按鈕val builder = AlertDialog.Builder(this)builder.setTitle("結算商品")builder.setMessage("客官抱歉,支付功能尚未開通,請下次再來")builder.setPositiveButton("我知道了", null)builder.create().show()}}override fun onCreateOptionsMenu(menu: Menu): Boolean {// 從menu_cart.xml中構建菜單界面布局menuInflater.inflate(R.menu.menu_cart, menu)return true}override fun onOptionsItemSelected(item: MenuItem): Boolean {val id = item.itemIdif (id == R.id.menu_shopping) { // 點擊了菜單項“去商場購物”// 跳轉到商場頁面val intent = Intent(this, ShoppingChannelActivity::class.java)startActivity(intent)} else if (id == R.id.menu_clear) { // 點擊了菜單項“清空購物車”// 清空購物車數據庫mCartHelper!!.deleteAll()ll_cart!!.removeAllViews()// 把最新的商品數量寫入共享參數SharedUtil.Companion.getIntance(this)!!.writeShared("count", "0")// 顯示最新的商品數量showCount(0)mCartGoods.clear()mGoodsMap.clear()Toast.makeText(this, "購物車已清空", Toast.LENGTH_SHORT).show()} else if (id == R.id.menu_return) { // 點擊了菜單項“返回”finish()}return true}// 聲明一個根據視圖編號查找商品信息的映射private val mCartGoods: HashMap<Int, CartInfo> = HashMap<Int, CartInfo>()// 聲明一個觸發上下文菜單的視圖對象private var mContextView: View? = nulloverride fun onCreateContextMenu(menu: ContextMenu, v: View, menuInfo: ContextMenuInfo) {// 保存該商品行的視圖,以便刪除商品時一塊從列表移除該行mContextView = v// 從menu_goods.xml中構建菜單界面布局menuInflater.inflate(R.menu.menu_goods, menu)}override fun onContextItemSelected(item: MenuItem): Boolean {val info: CartInfo? = mCartGoods[mContextView!!.id]val id = item.itemIdif (id == R.id.menu_detail) { // 點擊了菜單項“查看商品詳情”// 跳轉到查看商品詳情頁面goDetail(info!!.goods_id)} else if (id == R.id.menu_delete) { // 點擊了菜單項“從購物車刪除”val goods_id: Long = info!!.goods_id// 從購物車刪除商品的數據庫操作mCartHelper!!.delete("goods_id=$goods_id")// 從購物車列表中刪除該商品行ll_cart!!.removeView(mContextView)// 更新購物車中的商品數量var left_count: Int = mCount - info!!.countfor (i in mCartArray!!.indices) {if (goods_id == mCartArray!![i].goods_id) {left_count = mCount - mCartArray!![i].countmCartArray!!.removeAt(i)break}}// 把最新的商品數量寫入共享參數SharedUtil.Companion.getIntance(this)!!.writeShared("count", "" + left_count)// 顯示最新的商品數量showCount(left_count)Toast.makeText(this, "已從購物車刪除" + mGoodsMap[goods_id]!!.name, Toast.LENGTH_SHORT).show()mGoodsMap.remove(goods_id)refreshTotalPrice()}return true}// 跳轉到商品詳情頁面private fun goDetail(rowid: Long) {val intent = Intent(this, ShoppingDetailActivity::class.java)intent.putExtra("goods_id", rowid)startActivity(intent)}override fun onResume() {super.onResume()// 獲取共享參數保存的購物車中的商品數量mCount = SharedUtil.Companion.getIntance(this)!!.readShared("count", "0")!!.toInt()showCount(mCount)// 獲取商品數據庫的幫助器對象mGoodsHelper = GoodsDBHelper.Companion.getInstance(this, 1)// 打開商品數據庫的寫連接mGoodsHelper!!.openWriteLink()// 獲取購物車數據庫的幫助器對象mCartHelper = CartDBHelper.Companion.getInstance(this, 1)// 打開購物車數據庫的寫連接mCartHelper!!.openWriteLink()// 模擬從網絡下載商品圖片downloadGoods()// 展示購物車中的商品列表showCart()}override fun onPause() {super.onPause()// 關閉商品數據庫的數據庫連接mGoodsHelper!!.closeLink()// 關閉購物車數據庫的數據庫連接mCartHelper!!.closeLink()}// 聲明一個起始的視圖編號private val mBeginViewId = 0x7F24FFF0// 聲明一個購物車中的商品信息隊列private var mCartArray: ArrayList<CartInfo>? = ArrayList<CartInfo>()// 聲明一個根據商品編號查找商品信息的映射private val mGoodsMap: HashMap<Long, GoodsInfo?> = HashMap<Long, GoodsInfo?>()// 展示購物車中的商品列表private fun showCart() {// 查詢購物車數據庫中所有的商品記錄mCartArray = mCartHelper!!.query("1=1")Log.d(TAG, "mCartArray.size()=" + mCartArray!!.size)if (mCartArray == null || mCartArray!!.size <= 0) {return}// 移除線性視圖ll_cart下面的所有子視圖ll_cart.removeAllViews()// 創建一個標題行的線性視圖ll_rowvar ll_row = newLinearLayout(LinearLayout.HORIZONTAL, ViewGroup.LayoutParams.WRAP_CONTENT)ll_row.addView(newTextView(0, 2f, Gravity.CENTER, "圖片", Color.BLACK, 15))ll_row.addView(newTextView(0, 3f, Gravity.CENTER, "名稱", Color.BLACK, 15))ll_row.addView(newTextView(0, 1f, Gravity.CENTER, "數量", Color.BLACK, 15))ll_row.addView(newTextView(0, 1f, Gravity.CENTER, "單價", Color.BLACK, 15))ll_row.addView(newTextView(0, 1f, Gravity.CENTER, "總價", Color.BLACK, 15))// 把標題行添加到購物車列表ll_cart.addView(ll_row)for (i in mCartArray!!.indices) {val info: CartInfo = mCartArray!![i]// 根據商品編號查詢商品數據庫中的商品記錄val goods: GoodsInfo? = mGoodsHelper!!.queryById(info.goods_id)Log.d(TAG, "name=" + goods!!.name + ",price=" + goods.price + ",desc=" + goods.desc)mGoodsMap[info.goods_id] = goods// 創建該商品行的水平線性視圖,從左到右依次為商品小圖、商品名稱與描述、商品數量、商品單價、商品總價。ll_row = newLinearLayout(LinearLayout.HORIZONTAL, ViewGroup.LayoutParams.WRAP_CONTENT)// 設置該線性視圖的編號ll_row.id = mBeginViewId + i// 添加商品小圖val iv_thumb = ImageView(this)val iv_params = LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 2F)iv_thumb.layoutParams = iv_paramsiv_thumb.scaleType = ScaleType.FIT_CENTERiv_thumb.setImageBitmap(MainApplication.instance?.mIconMap?.get(info.goods_id))ll_row.addView(iv_thumb)// 添加商品名稱與描述val ll_name = LinearLayout(this)val params = LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT, 3F)ll_name.layoutParams = paramsll_name.orientation = LinearLayout.VERTICALll_name.addView(newTextView(-3, 1f, Gravity.LEFT, goods.name, Color.BLACK, 17))ll_name.addView(newTextView(-3, 1f, Gravity.LEFT, goods.desc, Color.GRAY, 12))ll_row.addView(ll_name)// 添加商品數量、單價和總價ll_row.addView(newTextView(1, 1f, Gravity.CENTER, "" + info.count, Color.BLACK, 17))ll_row.addView(newTextView(1,1f,Gravity.RIGHT,"" + goods.price.toInt(),Color.BLACK,15))ll_row.addView(newTextView(1,1f,Gravity.RIGHT,"" + (info.count * goods.price).toInt(),Color.RED,17))// 給商品行添加點擊事件ll_row.setOnClickListener { goDetail(info.goods_id) }// 給商品行注冊上下文菜單,為防止重復注冊,這里先注銷再注冊unregisterForContextMenu(ll_row)registerForContextMenu(ll_row)mCartGoods[ll_row.id] = info// 往購物車列表添加該商品行ll_cart.addView(ll_row)}// 重新計算購物車中的商品總金額refreshTotalPrice()}// 重新計算購物車中的商品總金額private fun refreshTotalPrice() {var total_price = 0for (info in mCartArray!!) {val goods: GoodsInfo? = mGoodsMap[info.goods_id]total_price += (goods!!.price * info.count).toInt()}tv_total_price.text = "" + total_price}// 創建一個線性視圖的框架private fun newLinearLayout(orientation: Int, height: Int): LinearLayout {val ll_new = LinearLayout(this)val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, height)ll_new.layoutParams = paramsll_new.orientation = orientationll_new.setBackgroundColor(Color.WHITE)return ll_new}// 創建一個文本視圖的模板private fun newTextView(height: Int,weight: Float,gravity: Int,text: String,textColor: Int,textSize: Int): TextView {val tv_new = TextView(this)if (height == -3) { // 垂直排列val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0, weight)tv_new.layoutParams = params} else { // 水平排列val params = LinearLayout.LayoutParams(0,if (height == 0) ViewGroup.LayoutParams.WRAP_CONTENT else ViewGroup.LayoutParams.MATCH_PARENT,weight)tv_new.layoutParams = params}tv_new.text = texttv_new.setTextColor(textColor)tv_new.setTextSize(TypedValue.COMPLEX_UNIT_SP, textSize.toFloat())tv_new.gravity = Gravity.CENTER or gravityreturn tv_new}private var mFirst: String? = "true" // 是否首次打開// 模擬網絡數據,初始化數據庫中的商品信息private fun downloadGoods() {// 獲取共享參數保存的是否首次打開參數mFirst = SharedUtil.Companion.getIntance(this)!!.readShared("first", "true")// 獲取當前App的私有存儲路徑val path: String = MainApplication.instance?.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString().toString() + "/"if (mFirst == "true") { // 如果是首次打開val goodsList: ArrayList<GoodsInfo> = GoodsInfo.defaultListfor (i in goodsList.indices) {val info: GoodsInfo = goodsList[i]// 往商品數據庫插入一條該商品的記錄val rowid: Long = mGoodsHelper!!.insert(info)info.rowid = rowid// 往全局內存寫入商品小圖val thumb = BitmapFactory.decodeResource(resources, info.thumb)MainApplication.instance?.mIconMap?.put(rowid, thumb)val thumb_path = path + rowid + "_s.jpg"FileUtil.saveImage(thumb_path, thumb)info.thumb_path = thumb_path// 往SD卡保存商品大圖val pic = BitmapFactory.decodeResource(resources, info.pic)val pic_path = "$path$rowid.jpg"FileUtil.saveImage(pic_path, pic)pic.recycle()info.pic_path = pic_path// 更新商品數據庫中該商品記錄的圖片路徑mGoodsHelper!!.update(info)}} else { // 不是首次打開// 查詢商品數據庫中所有商品記錄val goodsArray: ArrayList<GoodsInfo> = mGoodsHelper!!.query("1=1")for (i in goodsArray.indices) {val info: GoodsInfo = goodsArray[i]// 從指定路徑讀取圖片文件的位圖數據val thumb = BitmapFactory.decodeFile(info.thumb_path)// 把該位圖對象保存到應用實例的全局變量中MainApplication.instance?.mIconMap?.put(info.rowid, thumb)}}// 把是否首次打開寫入共享參數SharedUtil.Companion.getIntance(this)!!.writeShared("first", "false")}companion object {private const val TAG = "ShoppingCartActivity"} }實驗結果(實驗最終作品截圖說明)
實驗心得
1、熟悉Android五種主要存儲方式的用法,包括共享參數SharedPreferences、數據庫SQLite、SD卡文件、App的全局內存;
2、熟悉重要組件之一的應用Application的基本概念與常見用法,以及四大組件之一的內容提供器ContentProvider的基本概念與常見用法;
參考文章
總結
以上是生活随笔為你收集整理的《移动项目实践》实验报告——Android数据存储的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android11——DataBindi
- 下一篇: 《移动项目实践》实验报告——Androi