android快速开发框架QAndroid

前言

       因为工作经历的关系,做框架搭建工作至今已经7年了,进过一轮轮的演变和优化,才有现在QAndroid的原型。之前一直觉得不完美,针对性太强所以一直没有开源。后来了解到飞信、苏宁、优信他们的框架,感觉还不如QAndroid,所以才有了这篇文章。

简介

       QAndroid特别适合中小项目,目前已在多个项目中应用;他是一个简单小巧、开发快速并且维护简单的android app开发框架。基于DataBinding,使用kotlin开发跟迅捷。 框架已经集成okhttp、glide、fastjson和友盟统计。

       推荐使用mvvm模式,只需要开发维护model和xml两个文件即可。

       github地址:https://github.com/ddoolcg/QAndroid

集成

将其添加到存储库末尾的根build.gradle中:

allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}

 添加依赖项

// kotlin android插件
apply plugin: 'kotlin-android'
// kotlin的apt(编译时生成代码)
apply plugin: 'kotlin-kapt'
// 通过解析xml直接使用view,感兴趣的可以自行百度
//apply plugin: 'kotlin-android-extensions'
android {
    ...
    //开启dataBinding 
    dataBinding {
        enabled true
    }
}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    // QAndroid依赖
    api 'com.github.ddoolcg:QAndroid:1.4.1'
    // databinding注解依赖,编译时生成代码
    kapt 'com.android.databinding:compiler:3.1.4'
}

UIUtils工具类需要初始化、自定义http认证(也可以继承BaseApplication实现)
 

@Override
public void onCreate() {
     super.onCreate();
     if (UIUtils.init(this)) onInitMainProcesses();
     Token.INSTANCE.init("token", new Function1<Boolean, Unit>() {
         @Override
         public Unit invoke(Boolean aBoolean) {
              gotoLoin(aBoolean);
              return null;
          }
      });
  }


联网调用

//lambda不支持泛型套泛型的解析方式
DataEntry("url").joinProgressDialog(activity).formBody(map).post<T> {TODO()}
//抽象方法实现的方式调用,支持泛型套泛型的解析方式
DataEntry("url").joinProgressDialog(activity).formBody(map).post<T>(OnSuccessListener)
//默认统一处理接口调用失败
DataEntry.failDefault={code,data-> }


SharedPreferences操作
操作类
PreferenceKTX
多次put采用Any扩展

preferenceEdit {
    putBoolean()
    putString()
}


view的一些实用扩展
doOnGlobalLayout

view.doOnGlobalLayout {
    if (Boolean) {
        action()
        true
    } else {
        false
    }
}


doOnPreDraw

view.doOnPreDraw {
    action()
}


ViewGroup

viewGroup += view//addView
viewGroup -= view//removeView


页面实现demo(登陆)
activity:

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding = DataBindingUtil.setContentView<ActivityLoginBinding>(this, R.layout
                .activity_login)
        val login = Login(this).apply {
            titleText = "登陆"
            isShowBack = false
        }
        binding.login = login
    }

xml:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>

        <import type="android.text.TextUtils"/>

        <variable
            name="login"
            type="com.lcg.comment.model.Login"/>
    </data>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/bg_cover">

        <include
            android:id="@+id/i_title"
            layout="@layout/common_title"
            app:data="@{login}"/>

        <ImageView
            android:id="@+id/iv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/i_title"
            android:layout_centerHorizontal="true"
            android:layout_margin="@dimen/distance_item"
            android:src="@mipmap/ic_launcher"/>

        <EditText
            android:id="@+id/et_username"
            style="@style/edit"
            android:layout_below="@+id/iv"
            android:hint="用户名(手机号码)"
            android:inputType="number"
            android:text="@={login.username}"/>

        <EditText
            android:id="@+id/et_password"
            style="@style/edit"
            android:layout_below="@+id/et_username"
            android:ems="10"
            android:hint="密码(3-10位)"
            android:inputType="textPassword"
            android:text="@={login.password}"/>

        <Button
            android:id="@+id/btn_login"
            style="@style/btn_single"
            android:layout_below="@+id/et_password"
            android:layout_margin="@dimen/activity_horizontal_margin"
            android:enabled="@{!TextUtils.isEmpty(login.username) &amp;&amp; !TextUtils.isEmpty(login.password)}"
            android:onClick="@{login.login}"
            android:text="登录"/>

        <TextView
            android:id="@+id/tv_forget_password"
            style="@style/text_content"
            android:layout_height="48dp"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true"
            android:layout_below="@+id/btn_login"
            android:layout_marginLeft="@dimen/activity_horizontal_margin"
            android:gravity="center"
            android:onClick="@{login::gotoResetPassword}"
            android:text="忘记密码?"
            android:visibility="invisible"/>

        <TextView
            android:id="@+id/tv_regist"
            style="@style/text_content"
            android:layout_height="48dp"
            android:layout_alignParentEnd="true"
            android:layout_alignParentRight="true"
            android:layout_alignTop="@+id/tv_forget_password"
            android:layout_marginRight="@dimen/activity_horizontal_margin"
            android:gravity="center"
            android:onClick="@{login::gotoRegister}"
            android:text="立即注册"
            android:textColor="@color/blue"/>
    </RelativeLayout>
</layout>

model:

class Login(activity: BaseActivity) : BaseObservableMe(activity) {
    @get:Bindable
    var username: String = ""
        set(username) {
            field = username
            notifyPropertyChanged(BR.username)
        }
    @get:Bindable
    var password: String = ""
        set(password) {
            field = password
            notifyPropertyChanged(BR.password)
        }

    fun login(view: View) {
        if (!check())
            return
        val map = hashMapOf("username" to username, "password" to MD5.GetMD5Code(password))
        DataEntry(HttpUrl.login).joinProgressDialog(activity).formBody(map).post<AuthUser> {
            saveToken(it.token)
            PreferenceKTX.setConfig(it)
            try {
                val clazz: Class<Activity> = Class.forName("com.lcg.expressbus.MainActivity") as Class<Activity>
                activity.startActivity(clazz)
                activity.finish()
            } catch (e: Exception) {
                throw RuntimeException("com.lcg.expressbus.MainActivity is error!")
            }
        }
    }

    /**去注册*/
    fun gotoRegister(view: View) {
        RegisterActivity.start(activity)
    }

    /**去密码重置*/
    fun gotoResetPassword(view: View) {
        TODO()
    }

    protected open fun check(): Boolean {
        when {
            TextUtils.isEmpty(this.username) -> {
                UIUtils.showToastSafe("用户名不能为空")
                return false
            }
            !this.username.isPhone() -> {
                UIUtils.showToastSafe("请输入一个有效手机号码")
                return false
            }
            TextUtils.isEmpty(this.password) -> {
                UIUtils.showToastSafe("密码不能为空")
                return false
            }
            this.password.length < 2 -> {
                UIUtils.showToastSafe("密码必须大于两位")
                return false
            }
            else -> return true
        }
    }
}

开启友盟统计
在AndroidManifest.xml文件中修改

<meta-data android:name="UMENG_APPKEY" android:value="您的UMENG_APPKEY"/>


DataEntry无法满足你的需求可参考:
正常和异常数据都是通过200请求返回的

扩展联网框架

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值