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地址
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值