点餐系统的要点(一)
大四刚进入学校的培训基地,接的第一个项目是点餐系统,里面的知识点很多,因为服务器接口的问题,导致项目实现延长了三天,下面就是我在这个系统里所学到的知识与碰触到的误区:
先讲一下项目实现的顺序,登录系统->更新数据->点餐->下单->查询桌子->结算订单->查询订单->界面优化->实现自动登录。
1、登录系统:
服务器接口接受的参数为简单的字符串类型,其中包括一个接口标示,因为我是做移动端,服务端是老师写好的,具体实现内容等后面再讲,我是自己封装的okhttp3框架,还有使用过xuntils等第三方开源框架,封装框架我会在后面的博客里去写,先写一下这个项目的基本内容,这个项目的登录很简单,使用get或者post的方式获取json字符串,然后解析出我们需要的参数,传递的参数直接封装成方法传入值即可,主要注意对于异常的处理,比如空字符串转化int等,对于json的解析这里用的是谷歌的gson解析,使用javabean的方式将字符串转化成bean对象,再取值。
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
final ProgressBar progressBar =findViewById(R.id.progres_login);
progressBar.setVisibility(View.VISIBLE);
final String username = editText_user.getText().toString();
final String password = editText_pass.getText().toString();
if(username.length()!=0&&password.length()!=0){
okManager.postuserpassByurl(URL, "login", username, password, new Fun2() {
@Override
public void onResponse(String jsonValue) {
Gson gson =new Gson();
UserData data= gson.fromJson(jsonValue,UserData.class);
User user=gson.fromJson(data.getData(),User.class);
if (data.getIsSuccess()){
editor.putString("username",username);
editor.putString("password",password);
editor.commit();
startActivity(new Intent(LoginActivity.this,Index_Activity.class));
finish();
}
else {Toast.makeText(LoginActivity.this,"账号密码错误",Toast.LENGTH_SHORT).show();
}
progressBar.setVisibility(View.INVISIBLE);
}
});
}
`界面上我使用的自己设置的shape我个人比较喜欢半透明与简约所以!
shape是真的好用我们可以轻松的实现各种控件的自定义,
<solid android:color="@android:color/transparent"/>
<stroke android:color="#ffffff" android:width="1dp"/>
<corners android:radius="5dp"/>
<padding android:left="4dp" android:bottom="15dp" android:right="4dp" android:top="15dp"/>
</shape>
stroke设置边框的颜色与宽度,corners设置角的弧度,padding设置内边距,solid填充颜色这里我使用的透明。
这里就是登录的全部了我多写一点关于自己封装的okhttp3,我封装的okhttp3是使用handler异步消息处理与接口回调的方式实现网络请求。
先定义不同类型的接口,构造为实现的方法以备后面在返回数值时使用
/**
* 定义不同数据类型接口
*/
interface Fun1 {
void onResponse(JSONObject jsonObject);
}
interface Fun2 {
void onResponse(String jsonValue);
}
interface Fun3 {
void onResponse(byte[] src);
}
interface Fun4 {
void onResponse(Bitmap bitmap);
}
interface Fun5 {
void onResponse();
}
这里我们定义了五个不同的接口,接下来就是封装如何返回参数给我们的acticity这里我们使用handler异步消息处理
handler.post消息传递机制可以让我们在子线程传递我们从网上下载下来的数值通过接口回调的机制传递数据,这里我们开一个子线程,为什么要开子线程,因为在android中子线程无法实现更新ui并且住线程也就是ui线程不安全不能进行耗时操作会时时线程堵塞,这里我们如果需要进行数据获取必须要在子线程中,这里就是为什么我们用handler异步消息处理的关键所在,他可以通过异步处理的方法将数据获取到。这里讲到了如何传递我们的参数下面我们来说如何获取数值。
/**
* 回调函数下载JSONObject数据
*
* @param jsonValue
* @param callBack
*/
private void onSuccessJsonString(final String jsonValue, final Fun2 callBack) {
handler.post(new Runnable() {
@Override
public void run() {
if (callBack != null) {
callBack.onResponse(jsonValue);
}
}
});
}
public void postuserpassByurl(final String url, String to, final String username, final String password, final Fun2 callBack) {
FormBody formBody = new FormBody.Builder().add("to", to).add("code", username).add("password", password).build();
Request request = new Request.Builder().url(url).post(formBody).build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response != null) {
onSuccessJSONString(response.body().string(), callBack);
}
}
});
}
我们将此方法定义为pulic方便其他类使用,okhttp使用较简单使用步骤是先生成一个okhttpclient对象然后使用他的newcall方法可以看到他的newcall方法里面传递的参数为一个request的对象。 那我们就看一下这个request对象如何生成,生成方式时用bulier构造者的方式生成在构造者的基础上添加要请求的链接,和传递的数值,这里是post,还有get方法,get方法去获取服务器返回的数据时构造request则不同因为它不需要通过requestbody的方式传递参数但是他还是需要request去获取服务器放回的数据,
/**
* 通过url下载图片
*
* @param URL
* @param callBack
*/
public void getBitMapByUrl(final String URL, final Fun4 callBack) {
Request request = new Request.Builder().url(URL).build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response != null && response.isSuccessful()) {
byte[] data = response.body().bytes();
Bitmap bitmap = new CropSquareTrans().transform(BitmapFactory.decodeByteArray(data, 0, data.length));
callBack.onResponse(bitmap);
}
}
});
}
这里我们讲一个通过url下载图片的例子这里用请求的url然后通过onresponse返回的数据然后将图片通过bitmap解析出来这里我自定义了一个小的工具类用于实现图片剪裁的功能
public Bitmap transform(Bitmap source) {
int size = Math.min(source.getWidth(),source.getHeight());
int x = (source.getWidth()-size)/2;
int y = (source.getHeight()-size)/2;
Bitmap bitmap = Bitmap.createBitmap(source,x,y,size,size);
if (bitmap!=source){
source.recycle();
}
return bitmap;
}
因为我们从网上下载下来的图片为流,我们要通过bitmap工厂将它解析成bitmap的形式,上面随便理解一下就好了不是重点。
我们已经从网上获取到了数据,接下来我们要怎么讲数据返回给我们activity?
我们定义的这个工具类如何使用呢?
这里我再给大家讲解一个单例模式获取对象获取工具类的方式,单例模式,但是单例模式有并发性问题,我们这里稍作一下处理
/**
* 单例模式获取对象
*
* @return
*/
public static OKManager getInstance() {
OKManager instance = null;
if (instance==null){
synchronized (OKManager.class){
if (instance==null){
instance = new OKManager();
}
}
}
return instance;
}
我在写此单例模式时有好多种这里我们使用懒汉式我们保证只有一个对象,然后节省资源空间如果有人看了我的微博大家可以去网上找一些比较正规的单例模式的教程,后期加深理解以后我也会做单例模式的博客。
通过静态类直接通过类的方法去生成一个对象然后如果对象存在了 直接复用此对象,这是我的初步理解。
通过单例模式获得工具类对象之后使用工具类的方法。
okManager.postuserpassByurl(URL, "login", username, password, new Fun2() {
@Override
public void onResponse(String jsonValue) {
Gson gson =new Gson();
UserData data= gson.fromJson(jsonValue,UserData.class);
User user=gson.fromJson(data.getData(),User.class);
if (data.getIsSuccess()){
editor.putString("username",username);
editor.putString("password",password);
editor.commit();
startActivity(newIntent(LoginActivity.this,Index_Activity.class));
finish();
}
调用方法好我们传入我们所需要的参数和一个接口这个接口就是我们在上面声明的接口,这个接口是直接连接工具类执行后方法所传回的数据,因为我这里没有使用控件加载而是通过解析数据来进行跳转,如果要赋值给空间的话不要忘记要回到住线程毕竟handler的回调和网络请求都是在子线程中,子线程无法更新ui。如何回到主线程?
runOnuiThead(new Runable{…});重写里面的方法赋值给ui就可以了。