Kotlin+Retrofit+Dagger2+Rxjava

AS快捷鍵

展開空白包

在這裏插入圖片描述

java 文件轉Kotlin文件

在這裏插入圖片描述

工具使用

anko導包

導入design包(recycleView用)

  • 直接在這裏添加(要修改版本號)
    在這裏插入圖片描述
  • implementation ‘com.android.support:design:26+’

檢查是否有導航條

//獲取是否存在NavigationBar
    fun checkDeviceHasNavigationBar(context: Context): Boolean {
        var hasNavigationBar = false
        val rs = context.getResources()
        val id = rs.getIdentifier("config_showNavigationBar", "bool", "android")
        if (id > 0) {
            hasNavigationBar = rs.getBoolean(id)
        }
        try {
            val systemPropertiesClass = Class.forName("android.os.SystemProperties")
            val m = systemPropertiesClass.getMethod("get", String::class.java)
            val navBarOverride = m.invoke(systemPropertiesClass, "qemu.hw.mainkeys") as String
            if ("1" == navBarOverride) {
                hasNavigationBar = false
            } else if ("0" == navBarOverride) {
                hasNavigationBar = true
            }
        } catch (e: Exception) {

        }
        return hasNavigationBar
    }

dp和px互轉

//轉換dip爲px

fun Int.dp2px(): Int {
        return  TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, toFloat(),resources.displayMetrics).toInt()

    }

//轉換px爲dip

public static int pxtodp(Context context, int px) {

float scale = context.getResources().getDisplayMetrics().density;

return (int)(px/scale + 0.5f*(px>=0?1:-1));

}

去掉標題和沉浸式

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!--去掉標題-->
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>

        <!--半透明-->
        <item name="android:windowTranslucentStatus">true</item>
        <item name="android:windowTranslucentNavigation">true</item>

        <!--全透明-->
        <item name="android:statusBarColor">@android:color/transparent</item>
    </style>
</resources>

聲明成員變量的時候懶加載

//聲明成員變量的時候可以懶加載
    lateinit var v_home:RecyclerView
    override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View {
        val view = View.inflate(activity, R.layout.fragment_home, null)
        v_home=view.findViewById<RecyclerView>(R.id.rv_home)
        return view
    }

Kotlin語言學習之使用object和companion object修飾靜態類和靜態方法

object Util {
    fun getCurrentVersion(): String {
        return BuildConfig.VERSION_NAME
    }
}
class Util2 {
    companion object {
        fun getCurrentVersion(): String {
            return BuildConfig.VERSION_NAME
        }
    }
}

SliderLayout使用

inner class TitleHolder(item: View) : RecyclerView.ViewHolder(item) {
        val slideLayout: SliderLayout

        init {
            slideLayout = item.findViewById<SliderLayout>(R.id.slider)
        }

        fun bindDate(data: String) {
            if (url_maps.size==0){
                url_maps.put("Hannibal", "http://static2.hypable.com/wp-content/uploads/2013/12/hannibal-season-2-release-date.jpg");
                url_maps.put("Big Bang Theory", "http://tvfiles.alphacoders.com/100/hdclearart-10.png");
                url_maps.put("House of Cards", "http://cdn3.nflximg.net/images/3093/2043093.jpg");
                url_maps.put("Game of Thrones", "http://images.boomsbeat.com/data/images/full/19640/game-of-thrones-season-4-jpg.jpg");
            }

            for ((key,value) in url_maps){
                val textSliderView = TextSliderView(context)
                textSliderView.description(key).image(value)
                slideLayout.addSlider(textSliderView)

            }
        }
    }

Retorfit簡介

1.引入配置

	compile 'com.google.code.gson:gson:2.2.4'
    compile'com.squareup.retrofit2:retrofit:2.1.0'
    compile 'com.squareup.retrofit2:converter-gson:2.1.0'
  • 2.實例代碼
class HomeFragmentPresenter(val ihomeFragment: IHomeFragment) {
    val takeoutService: TakeoutService

    init {
        val retrofit = Retrofit.Builder()
                .baseUrl("http://192.168.2.118:8080/TakeoutService/")
                .addConverterFactory(GsonConverterFactory.create())
                .build()

        takeoutService = retrofit.create<TakeoutService>(TakeoutService::class.java!!)
    }


    fun getHomeInfo() {
        val homeCall = takeoutService.getHomeInfo()
        homeCall.enqueue(object : Callback<ResponseInfo> {
            override fun onResponse(call: Call<ResponseInfo>?, response: Response<ResponseInfo>?) {
                if (response == null) {
                    Log.e("home", "服務器沒有返回成功")
                } else {
                    if (response.isSuccessful) {
                        val responseInfo = response.body()
                        if (responseInfo.code.equals("0")) {
                            val json = responseInfo.data
                            parserJson(json)
                        } else {
                            Log.e("home", "服務器返回的數據錯誤responseInfo.code:${responseInfo.code}")
                        }
                    } else {
                        Log.e("home", "服務器返回的代碼錯誤response.code():${response.code()}")
                    }

                }
            }

            override fun onFailure(call: Call<ResponseInfo>?, t: Throwable?) {
                Log.e("home", "服務器沒有連接成功")
            }

        })

//        ihomeFragment.onHomeFailed()
//        ihomeFragment.onHomeSuccess()
    }

    private fun parserJson(json: String) {
        val gson = Gson()
        val jsonObject = JSONObject(json)
        val nearby = jsonObject.getString("nearbySellerList")
        val nearbySellers: List<Seller> = gson.fromJson(nearby, object : TypeToken<List<Seller>>() {}.type)

        val other = jsonObject.getString("otherSellerList")
        val otherSellers: List<Seller> = gson.fromJson(other, object : TypeToken<List<Seller>>() {}.type)

        if(nearbySellers.isNotEmpty() ||otherSellers.isNotEmpty()){
            ihomeFragment.onHomeSuccess(nearbySellers,otherSellers)
        }else{
            ihomeFragment.onHomeFailed()
        }
    }
}

dagger2配置

  • 理清關係
    在這裏插入圖片描述
  • 代碼module():
  • 因爲這種方式是通過類名來注入的,所以的module不需要也不能傳IHomeFragment,這樣會找不到對應的類注入,而module是由編譯器管理的他持有V層是(HomeFragment或者IHomeFragment都不會影響自己工程本身的耦合度),本身工程裏的Presenter持有的是IHomeFragment就已經解了耦合
@Module
class HomeFragmentMoudle(val homeFragment: HomeFragment) {

    @Provides fun providerHomeFragmentPresenter(): HomeFragmentPresenter {
        return HomeFragmentPresenter(homeFragment)
    }
}
  • componet代碼
@Component(modules = arrayOf(HomeFragmentMoudle::class)) interface HomeFragmentComponet{
    fun inject(iHomeFragment: IHomeFragment)
}
  • 四個組件
    • 編譯器在rebuild之後會根據註解生成component的實現類,前面加了一個dagger
    • 這個component類通過建造者模式爲自己賦值一個module
    • 最後component的注入方法,調用了module的@Provides 設置的方法返回了一個單例的presenter
    • 全過程是@component找到@injecti調用自己的inject,找到@module調用他的provide
  • 注意如果一個component的包含多個module,有自定義構造方法的module,一定要在注入前自己構造,(如果沒有定義,系統會默認調用無參的構造),如果不構造會報錯。就是系統實現的component的類,在使用前一定要拿到對應的module(沒有自定義構造函數的,他會調用默認的無參構造),否則他組裝不出來
@Component(modules = arrayOf(HomeFragmentMoudle::class,LoginActivityMoudle::class))
interface HomeFragmentComponet{
    fun inject(homeFragment: HomeFragment)
    fun inject(loginActivity: LoginActivity)
}

短信驗證(不經過自己的服務器)

在這裏插入圖片描述

handle泄漏

var handle= @SuppressLint("HandlerLeak")
    object :Handler(){
        override fun handleMessage(msg: Message?) {
            when(msg!!.what){
                TIME_MINUT-> tv_user_code.text = "剩餘時間(${time})秒"
                TIME_OUT->{
                    tv_user_code.isEnabled=true
                    time=60
                    tv_user_code.text="點擊重發"
                }
            }
        }
    }

倒計時代碼

companion object {
        val TIME_MINUT = -1
        val TIME_OUT = 0
    }

    var handle = @SuppressLint("HandlerLeak")
    object : Handler() {
        override fun handleMessage(msg: Message?) {
            when (msg!!.what) {
                TIME_MINUT -> tv_user_code.text = "剩餘時間(${time})秒"
                TIME_OUT -> {
                    tv_user_code.isEnabled = true
                    time = 60
                    tv_user_code.text = "點擊重發"
                }
            }
        }
    }

    var time = 60

    inner class TimeTask : Runnable {
        override fun run() {
            while (time > 0) {
                handle.sendEmptyMessage(TIME_MINUT)
                SystemClock.sleep(1000)
                time--
            }
            handle.sendEmptyMessage(TIME_OUT)
        }

    }

ormlite

  • 加依賴
	compile 'com.j256.ormlite:ormlite-android:5.0'
    compile 'com.j256.ormlite:ormlite-core:5.0'
使用(原生的看下面)
  • 創建對象關係映射

@DatabaseTable(tableName = "t_user") class User {

    @DatabaseField(id = true) var id: Int = 0  //使用指定id
    @DatabaseField(columnName = "name") var name: String? = null
    @DatabaseField(columnName = "balance") var balance: Float = 0.toFloat()
    @DatabaseField(columnName = "discount") var discount: Int = 0
    @DatabaseField(columnName = "integral") var integral: Int = 0
    @DatabaseField(columnName = "phone") var phone: String? = null

}
  • 創建類繼承 OrmLiteSqliteOpenHelper(把庫創建好)
class TakeOutOpenHelper(val context:Context): OrmLiteSqliteOpenHelper(context,"kotlin.db",null,1) {
    override fun onCreate(database: SQLiteDatabase?, connectionSource: ConnectionSource?) {
        TableUtils.createTable(connectionSource, User::class.java)
    }
    override fun onUpgrade(database: SQLiteDatabase?, connectionSource: ConnectionSource?, oldVersion: Int, newVersion: Int) {
    }
}
  • 使用(事務管理,增 改 查)
 override fun parserJson(json: String) {
        val gson = Gson()
        val user = gson.fromJson(json, User::class.java)

        if (user != null) {
            TakeOutApp.user = user
            var connection: AndroidDatabaseConnection? = null
            var savePoint: Savepoint? = null

            try {
                val takeoutOpenHelper = TakeOutOpenHelper(loginActivity as Context)

                //事務處理
                connection = AndroidDatabaseConnection(takeoutOpenHelper.writableDatabase, true)
                savePoint = connection.setSavePoint("start")

                val userDao: Dao<User, Int> = takeoutOpenHelper.getDao(User::class.java)
                //保證如果已有此用戶,就不需再創建了
                //  userDao.create(user)
//            userDao.createOrUpdate(user)


                val userList: List<User> = userDao.queryForAll()
                var isOlderUser = false
                for (i in 0 until userList.size) {
                    val u = userList.get(i)
                    if (u.id.equals(user.id)) {
                        isOlderUser = true
                    }
                }

                if (isOlderUser) {
                    //是老用戶
                    userDao.update(user)
                    Log.e("LoginActivityPresenter", "老用戶登錄更新信息")
                } else {
                    userDao.create(user)
                    Log.e("LoginActivityPresenter", "新用戶登錄")
                }
                connection.commit(savePoint)
                Log.e("LoginActivityPresenter", "事務正常")
                loginActivity.onLoginSuccess(user)
            } catch (e: Exception) {
                Log.e("LoginActivityPresenter", "事務異常")
                if (connection != null)
                    connection.rollback(savePoint)
            }
        }
    }
回憶原生數據庫的封裝
  • SQLiteOpenHelper:Sqliteopenhelp(Context context)只是配置數據庫,就是說構造方法調用的時候,數據庫並沒有創建,要等到,調用者用help.getWritableDatabase(),數據看才真正創建,並作爲參數傳入到onCreate方法裏,創建數據庫裏面的表(當然創建表的動作可以放到Dao裏完成)
public class Sqliteopenhelp extends SQLiteOpenHelper {

	public Sqliteopenhelp(Context context) {
		super(context, "config.db", null, 1);
		// TODO Auto-generated constructor stub
		System.out.println("111111111111");
	}

	@Override
	public void onCreate(SQLiteDatabase db) {
		// TODO Auto-generated method stub
		System.out.println("數據庫已經創建");
		db.execSQL("create table help(id integer primary key autoincrement,name varchar(20),age varchar(20))");
	}

	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		// TODO Auto-generated method stub
		
	}

}
  • PersonDao:一個Dao對應數據庫裏的一張表
public class PersonDao {
   private Context context;
   private Sqliteopenhelp sp;
   
   public PersonDao(Context context) {
   	this.context=context;
   	sp = new Sqliteopenhelp(context);
   }
   
   public void add(String name,String age){
   	SQLiteDatabase db = sp.getWritableDatabase();
   	db.execSQL("insert into help(name,age)values('"+name+"','"+age+"')");
   }
   public void delete(String name){
   	SQLiteDatabase db = sp.getWritableDatabase();
   	db.execSQL("delete from help where name='"+name+"' ");
   }
   public void update(String age){
   	SQLiteDatabase db = sp.getWritableDatabase();
   	db.execSQL("update help set age='"+age+"' where name='zhangsan' ");
   }
   public void query(String name){
   	SQLiteDatabase db = sp.getWritableDatabase();
   	Cursor rq = db.rawQuery("select age from help where name='zhangsan'", null);
   	while(rq!=null&&rq.moveToFirst())
   		
   	System.out.println(rq.getString(0));
   }
}
  • 調用:拿到Dao對數據庫操作裏面的表
public class MainActivity extends Activity {

	private PersonDao pd;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		pd = new PersonDao(this);
	}
	public void insert(View v){
		pd.add("張三", "11");
	}
	public void delete(View v){
		pd.delete("張三");
	}
	public void update(View v){
		pd.update("11");
	}
	
	public void query(View v){
		pd.query("張三");	
	}
}

外賣的業務邏輯

在這裏插入圖片描述

極光推送

在這裏插入圖片描述

數據填充
 override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): RecyclerView.ViewHolder {
        //list類型在填充的時候,如果是matchParent的方式填充,下面的方法沒有指定parent,
        // 那麼是安裝unspeciay的模式,那麼按最小的填充會填充不滿
        val item = View.inflate(context, R.layout.item_order_item, null)
        //應該這樣填充
        //   val item = LayoutInflater.from(context).inflate(R.layout.item_order_item, parent, false)
        return OrderViewHolder(item)

在這裏插入圖片描述

下拉刷新的RecyclerView—SwipeRefreshLayout
<android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/srl_order"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.v7.widget.RecyclerView
            android:id="@+id/rv_order_list"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </android.support.v4.widget.SwipeRefreshLayout>
  • 使用
swipesRefreshLayout = view.find<SwipeRefreshLayout>(R.id.srl_order)
        swipesRefreshLayout.setOnRefreshListener{
            if (TakeOutApp.user.id==-1){
                toast("請重新登錄")
            }else{
                orderFragmentPresenter.getListInfo(TakeOutApp.user.id.toString())
            }
        }


  override fun onOrderFailed() {
        toast("服務器繁忙")
        swipesRefreshLayout.isRefreshing=false
    }

    override fun onOrderSuccess(orders: List<Order>) {
        orderRvAdapter.setData(orders)
        swipesRefreshLayout.isRefreshing=false
    }
極光推送
  • 注意清單文件中的權限不能重名
  • 構建錯誤要看gradle console ,receiver可能重名
  • intent處理
 val bundle = intent.extras
            if (bundle != null) {
                val message: String? = bundle.getString(JPushInterface.EXTRA_MESSAGE)
                if (!TextUtils.isEmpty(message)) {
                    Log.e("MyReceiver:message", message)
                }

                val extras: String? = bundle.getString(JPushInterface.EXTRA_EXTRA)
                if (!TextUtils.isEmpty(extras)) {
                    Log.e("MyReceiver:extras", extras)
                }

            }
觀察者(系統自帶的)

在這裏插入圖片描述

  • 使用
  • 被觀察者繼承Observable設置成單例
class OrderObservable :Observable() {
    companion object {

        val instance =OrderObservable()
        /* 訂單狀態
       * 1 未支付 2 已提交訂單 3 商家接單  4 配送中,等待送達 5已送達 6 取消的訂單*/
        val ORDERTYPE_UNPAYMENT = "10"
        val ORDERTYPE_SUBMIT = "20"
        val ORDERTYPE_RECEIVEORDER = "30"
        val ORDERTYPE_DISTRIBUTION = "40"
        // 騎手狀態:接單、取餐、送餐
        val ORDERTYPE_DISTRIBUTION_RIDER_RECEIVE = "43"
        val ORDERTYPE_DISTRIBUTION_RIDER_TAKE_MEAL = "46"
        val ORDERTYPE_DISTRIBUTION_RIDER_GIVE_MEAL = "48"

        val ORDERTYPE_SERVED = "50"
        val ORDERTYPE_CANCELLEDORDER = "60"
    }

    fun newInstance(msg :String){
        setChanged()//設置標記
        instance.notifyObservers(msg)//通知
    }
}

  • 拿到了數據之後通過newInstance通知被觀察者
  • 觀察者繼承Observer,把自己添加到被觀察者通知的對象裏
init {
        OrderObservable.instance.addObserver(this)
    }
  • 觀察者複寫update方法更新
 override fun update(o: Observable?, arg: Any?) {
        val json = arg as String
        val jsonObject = JSONObject(json)
        val id = jsonObject.getString("id")

        val pushType = jsonObject.getString("type")
        for (order in orders){
            if (order.id!!.equals(id)){
                order.type=pushType
                notifyItemChanged(orders.indexOf(order))
                break
            }
        }

    }
RecycleView 的item事件:是在holder中實現(對於每一個holder所處的position,可以存放到成員變量裏面)
  • 注意不要忘記設置
rvGoodsType.layoutManager=LinearLayoutManager(activity)
BottomSheet使用
  • 依賴
compile 'com.flipboard:bottomsheet-commons:1.5.1'
compile 'com.flipboard:bottomsheet-core:1.5.1'
StickyListHeaders使用
  • 依賴
compile 'se.emilsjolander:stickylistheaders:2.7.0'
由於用了v4包下的FragmentPagerAdapter,導致需要v4的Fragment,但是v4的Fragment不兼容android.app.Fragment,所以要導入v13的包,用v13下的FragmentPagerAdapter

在這裏插入圖片描述
在這裏插入圖片描述

處理左右聯動的時候防止互相反覆刷

在這裏插入圖片描述

  • 要區分右邊滑動是用戶手動的,還是因爲左邊點擊驅動的
    • 用戶點擊的只會驅動右邊的onScroll方法
    • 而用戶滑動會驅動右邊的onScroll和onScrollStateChanged
//表示是不是客戶手滑動
    var isCustomScroll = false

//爲右邊設置監聽,讓右邊驅動左邊
        slhGoodslist.setOnScrollListener(object : AbsListView.OnScrollListener {
            override fun onScroll(view: AbsListView?, firstVisibleItem: Int, visibleItemCount: Int, totalItemCount: Int) {
                //客戶手滑動的才刷新右邊
                if (isCustomScroll) {
                    Log.e("onScroll", "onScroll")
                    //找到所屬的typeID
                    val typeId = stickyAdapter.goodsList.get(firstVisibleItem).typeId
                    rvGoodsTypeAdapter.setSelectItem(typeId)
                }
            }

            override fun onScrollStateChanged(view: AbsListView?, scrollState: Int) {
                //是客戶手滑動的,不是左邊驅動的
                isCustomScroll = true
                Log.e("onScrollStateChanged", "onScrollStateChanged")
            }
        })


//左邊itemView的點擊事件
            itemView.setOnClickListener {
                val goodsfragment: GoodsFragment = (context as BusinessActivity).fragments.get(0) as GoodsFragment
                val goodsFragmentPresenter = goodsfragment.goodsFragmentPresenter
                //不是客戶點的
                goodsFragmentPresenter.isCustomScroll=false
                currentSelectItem = mPosition
                goodsFragmentPresenter.setRightSelection(goodsTypeList.get(currentSelectItem).id)
                notifyDataSetChanged()
            }
  • 左邊刷新右邊,要判斷,變化了才notify防止無效刷新,浪費性能
    //留給右邊爲左邊設置選定item
    fun setSelectItem(typeId: Int) {
        //要變化了才刷,防止不必要的刷新
        if (goodsTypeList.get(currentSelectItem).id == typeId) return
        var select: Int = -1
        for (goodsType in goodsTypeList) {
            if (goodsType.id == typeId) {
                select = goodsTypeList.indexOf(goodsType)
            }
        }
        if (select != -1)
            currentSelectItem = select
        notifyDataSetChanged()
    }
  • 讓左邊的選中條目展示出來:RecyclerView沒有setSelectItem方法
//讓左邊的選中條目展示出來
    fun showTypeSelect(currentSelectItem: Int) {
        val firstVisibleItemPosition = (rvGoodsType.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()
        val lastVisibleItemPosition = (rvGoodsType.layoutManager as LinearLayoutManager).findLastVisibleItemPosition()
        if (currentSelectItem<firstVisibleItemPosition||currentSelectItem>lastVisibleItemPosition){
            rvGoodsType.scrollToPosition(currentSelectItem)
        }
    }
處理動畫
  • 拋物線動畫(動畫執行者是在最頂層的控件)
fun parabolaAnimation(srcLocation:IntArray,desLocation:IntArray): AnimationSet {
        val animationSet = AnimationSet(false)
        animationSet.duration = DURATION

        val xTranslateAnimation = TranslateAnimation(Animation.ABSOLUTE, 0f,
                Animation.ABSOLUTE, desLocation[0].toFloat()-srcLocation[0].toFloat(),
                Animation.ABSOLUTE, 0f,
                Animation.ABSOLUTE, 0f)
        xTranslateAnimation.duration = DURATION

        val yTranslateAnimation = TranslateAnimation(Animation.ABSOLUTE, 0f,
                Animation.ABSOLUTE, 0f,
                Animation.ABSOLUTE, 0f,
                Animation.ABSOLUTE, desLocation[1].toFloat()-srcLocation[1].toFloat())
        yTranslateAnimation.setInterpolator(AccelerateInterpolator())
        yTranslateAnimation.duration = DURATION


        animationSet.addAnimation(xTranslateAnimation)
        animationSet.addAnimation(yTranslateAnimation)
        return animationSet
    }
  • 動畫監聽如果只需要實現裏面部分的方法,可以在工具類裏把監聽接口實現好
            //動畫監聽
            //繼承原始的接口
//            parabolaAnimation.setAnimationListener(object : Animation.AnimationListener {
//                override fun onAnimationRepeat(animation: Animation?) {}
//
//                override fun onAnimationEnd(animation: Animation?) {
//                    (context as BusinessActivity).removeImagebutton(ib)
//                }
//
//                override fun onAnimationStart(animation: Animation?) {}
//
//            })
            //繼承實現好接口的對象
            parabolaAnimation.setAnimationListener(object : MyAnimationUtils.animationlistner() {
                override fun onAnimationEnd(animation: Animation?) {
                    (context as BusinessActivity).removeImagebutton(ib)
                }
            })
        }

BottomSheetLayout的使用

 fun showOrHideCart() {

        if (bottomSheetLayout.isSheetShowing) {
            //關閉內容顯示
            bottomSheetLayout.dismissSheet()
        } else {
            bottomSheetLayout.showWithSheetView(bottomSheetView)
        }

    }

startActivity帶intent

//發
val intent = Intent(context, BusinessActivity::class.java)
var hasSelectInfo=false

intent.putExtra("hasSelectInfo",hasSelectInfo)
intent.putExtra("seller",mSeller)
context.startActivity(intent)

//收
  if (intent.hasExtra("hasSelectInfo")) {
            hasSelectInfo = intent.getBooleanExtra("hasSelectInfo", false)
            seller = intent.getSerializableExtra("seller") as Seller
        }

startActivityForResult

//發
	startActivityForResult(intent, 1002)
	
  	override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if(resultCode == 200){
            if(data!=null) {
                val address :RecepitAddressBean = data.getSerializableExtra("address") as RecepitAddressBean
                tv_name.text = address.username
                //TODO:其他字段類似賦值
            }
        }
    }

//收
 val intent = Intent()
                    intent.putExtra("addAddressBean",address)
                    (context as Activity).setResult(200,intent)
                    (context as Activity).finish()

application類的單例(其他的單例只要類名class換object就行)

class TakeOutApp : MobApplication() {
    companion object {
        lateinit var instance: TakeOutApp
    }

    override fun onCreate() {
		instance=this 
    }
}

注意集合的遍歷不可以移除,先記錄再統一移除

fun clearCacheSelectedInfo(sellerId: Int) {
        var infos = TakeOutApp.instance.cacheSelectedInfolist
        val temp = ArrayList<CacheSelectedInfo>()
        for (i in 0..infos.size - 1) {
            val info = infos[i]
            if (info.sellerId == sellerId) {
//                infos.remove(info)
                temp.add(info)
            }
        }
        infos.removeAll(temp)
    }

dialog處理

var builder = AlertDialog.Builder(this)
            builder.setTitle("確認都不吃了麼?")
            builder.setPositiveButton("是,我要減肥", object : DialogInterface.OnClickListener {
                override fun onClick(dialog: DialogInterface?, which: Int) {
                    //開始清空購物車,把購物車中商品的數量重置爲0
                    val goodsFragment: GoodsFragment = fragments.get(0) as GoodsFragment
                    goodsFragment.goodsFragmentPresenter.clearAll()
                }
            })
            builder.setNegativeButton("不,我還要喫", object : DialogInterface.OnClickListener {
                override fun onClick(dialog: DialogInterface?, which: Int) {}
            })
            builder.show()

表單檢測工具類

fun checkReceiptAddressInfo(): Boolean {
        val name = et_name.getText().toString().trim()
        if (TextUtils.isEmpty(name)) {
            Toast.makeText(this, "請填寫聯繫人", Toast.LENGTH_SHORT).show()
            return false
        }
        val phone = et_phone.getText().toString().trim()
        if (TextUtils.isEmpty(phone)) {
            Toast.makeText(this, "請填寫手機號碼", Toast.LENGTH_SHORT).show()
            return false
        }
        if (!isMobileNO(phone)) {
            Toast.makeText(this, "請填寫合法的手機號", Toast.LENGTH_SHORT).show()
            return false
        }
        val receiptAddress = et_receipt_address.getText().toString().trim()
        if (TextUtils.isEmpty(receiptAddress)) {
            Toast.makeText(this, "請填寫收穫地址", Toast.LENGTH_SHORT).show()
            return false
        }
        val address = et_detail_address.getText().toString().trim()
        if (TextUtils.isEmpty(address)) {
            Toast.makeText(this, "請填寫詳細地址", Toast.LENGTH_SHORT).show()
            return false
        }
        return true
    }
object SMSUtil {
    /**
     * 判斷手機號碼是否合理
     * y
     */
    fun judgePhoneNums(activity: Activity, phoneNums: String): Boolean {
        if (isMatchLength(phoneNums, 11) && isMobileNO(phoneNums)) {
            return true
        }
        Toast.makeText(activity, "手機號碼輸入有誤!", Toast.LENGTH_SHORT).show()
        return false
    }

    /**
     * 驗證手機格式
     */
    fun isMobileNO(mobileNums: String): Boolean {
        /*
         * 移動:134、135、136、137、138、139、150、151、157(TD)、158、159、187、188
		 * 聯通:130、131、132、152、155、156、185、186 電信:133、153、180、189、(1349衛通)
		 * 總結起來就是第一位必定爲1,第二位必定爲3或5或8,其他位置的可以爲0-9
		 */
        val telRegex = "[1][358]\\d{9}"// "[1]"代表第1位爲數字1,"[358]"代表第二位可以爲3、5、8中的一個,"\\d{9}"代表後面是可以是0~9的數字,有9位。
        if (TextUtils.isEmpty(mobileNums))
            return false
        else
            return mobileNums.matches(telRegex.toRegex())
    }


    /**
     * 判斷一個字符串的位數

     * @param str
     * *
     * @param length
     * *
     * @return
     */
    fun isMatchLength(str: String, length: Int): Boolean {
        if (str.isEmpty()) {
            return false
        } else {
            return if (str.length == length) true else false
        }
    }

    /**
     * 權限校驗
     * @param activity
     */
    fun checkPermission(activity: Activity) {
        if (Build.VERSION.SDK_INT >= 23) {
            val readPhone = activity.checkSelfPermission(Manifest.permission.READ_PHONE_STATE)
            val receiveSms = activity.checkSelfPermission(Manifest.permission.RECEIVE_SMS)
            val readSms = activity.checkSelfPermission(Manifest.permission.READ_SMS)
            val readContacts = activity.checkSelfPermission(Manifest.permission.READ_CONTACTS)
            val readSdcard = activity.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE)

            var requestCode = 0
            val permissions = ArrayList<String>()
            if (readPhone != PackageManager.PERMISSION_GRANTED) {
                requestCode = requestCode or (1 shl 0)
                permissions.add(Manifest.permission.READ_PHONE_STATE)
            }
            if (receiveSms != PackageManager.PERMISSION_GRANTED) {
                requestCode = requestCode or (1 shl 1)
                permissions.add(Manifest.permission.RECEIVE_SMS)
            }
            if (readSms != PackageManager.PERMISSION_GRANTED) {
                requestCode = requestCode or (1 shl 2)
                permissions.add(Manifest.permission.READ_SMS)
            }
            if (readContacts != PackageManager.PERMISSION_GRANTED) {
                requestCode = requestCode or (1 shl 3)
                permissions.add(Manifest.permission.READ_CONTACTS)
            }
            if (readSdcard != PackageManager.PERMISSION_GRANTED) {
                requestCode = requestCode or (1 shl 4)
                permissions.add(Manifest.permission.READ_EXTERNAL_STORAGE)
            }
            if (requestCode > 0) {
                val permission = arrayOfNulls<String>(permissions.size)
                activity.requestPermissions(permissions.toTypedArray(), requestCode)
                return
            }
        }
    }
}

數據庫升級後

  • onCreate 新增的東西要寫進 onUpgrade(給升級的用的)
  • versionCode 要增加
class TakeOutOpenHelper(val context:Context): OrmLiteSqliteOpenHelper(context,"kotlin.db",null,2) {
    override fun onCreate(database: SQLiteDatabase?, connectionSource: ConnectionSource?) {
        TableUtils.createTable(connectionSource, User::class.java)
        TableUtils.createTable(connectionSource, Address::class.java)
    }

    override fun onUpgrade(database: SQLiteDatabase?, connectionSource: ConnectionSource?, oldVersion: Int, newVersion: Int) {
        TableUtils.createTable(connectionSource, Address::class.java)
    }
}

ormlite Dao的封裝

class AddressDao(val context: Context) {
    lateinit var addressDao: Dao<AddressBean, Int>
    init {
        val takeOutOpenHelper = TakeOutOpenHelper(context)
        addressDao = takeOutOpenHelper.getDao(AddressBean::class.java)

    }

    fun addAddressBean(addressBean: AddressBean){
        try {
            addressDao.create(addressBean)
        }catch (e:Exception){
            Log.e("addAddressBean", e.localizedMessage)
        }
    }

    fun deleteAddressBean(addressBean: AddressBean){
        try {
            addressDao.delete(addressBean)
        }catch (e:Exception){
            Log.e("deleteAddressBean", e.localizedMessage)
        }
    }

    fun updateAddressBean(addressBean: AddressBean){
        try {
            addressDao.update(addressBean)
        }catch (e:Exception){
            Log.e("updateAddressBean", e.localizedMessage)
        }
    }
    
    fun queryAllAddressBean( ):List<AddressBean>{
        try {
            return addressDao.queryForAll()
        }catch (e:Exception){
            Log.e("updateAddressBean", e.localizedMessage)
            return arrayListOf()
        }
    }
}

報錯事務異常:java.lang.IllegalArgumentException: Can’t find a no-arg constructor for class com.xjd.mvplearntakeout.model.bean.AddressBean

  • 把自定義的構造函數繼承系統自帶的無參 :this()
@DatabaseTable(tableName = "t_address")
class AddressBean() : Serializable{
    constructor(id: Int, user: String, sex: String, phone: String, phone_other: String, adress: String, aderss_other: String, label: String, userId: String):this() {      
}

地圖位置模擬,可以用(在線地圖經緯度

git地址

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章