android大作业快递代拿软件,安卓大作业——校内快递代取app的一些总结

对大作业用到技术以及遇到的一些问题的总结

先上图了解基本功能

5d30416c95f8?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

注册

5d30416c95f8?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

登录

5d30416c95f8?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

主界面

5d30416c95f8?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

帮我取件

5d30416c95f8?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

帮人代取

在未被确认为接单人时,只能查看酬金、包裹大小和收货地址,无法查看发布者个人信息

5d30416c95f8?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

滑动菜单

5d30416c95f8?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

我的发布

可选择接单人

5d30416c95f8?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

接单人信息

可查看多个接单人的基本信息,并确定其中一个作为最终接单人

5d30416c95f8?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

我的接单

被发布者确定为接单人之后,才显示发布者的基本信息和快递取件码

下面开始介绍用到的方法

在开发中遇到的大坑:Bmob云数据库不支持多表联合查询;在update数据时,不相关的数据可能会被初始化为0

语法类似于SQLite

一、注册MD5加密,登录MD5解密

新建MD5类

public class MD5 {

public static String getMD5(String c_password) {

try {

// 生成一个MD5加密计算摘要

MessageDigest md = MessageDigest.getInstance("MD5");

// 调用update方法计算MD5函数(参数:将密码串转换为操作系统的字节编码)

md.update(c_password.getBytes());

// digest()最后返回md5的hash值,返回值为8位的字符串,但此方法要先调用update

// BigInteger函数则将8位的字符串转换成16位hex值,用字符串来表示;得到字符串形式的hash值,数值从1开始

// BigInteger会把0省略掉,需补全至32位,重写一个方法将16位数转换为32位数

String md5 =new BigInteger(1, md.digest()).toString(16);

return md5;

}catch (Exception e) {

throw new RuntimeException("MD5加密错误:" + e.getMessage(), e);

}

}

}

使用此类的静态方法,将输入的密码作为参数,加密后的字符串赋值给md5_pwd并存储到数据库

md5_pwd=MD5.getMD5(input_pwd);

登录时将输入的密码以同样以MD5加密的方式转换为字符串,与数据库中的字符串比较,若相同则登录成功

md5pwd=MD5.getMD5(pwd);

二、订单列表中头像的异步显示

订单列表是通过订单表的订单id查询出来的记录,但头像为用户的头像,存储在用户信息表中,而Bmob云数据库不支持多表查询,故此处用了异步机制,让图片在子线程中加载。订单表中存有发布者id,通过查询用户信息表中此id的记录,将图片地址取出来,再显示在列表中。但后来请教老师,老师建议在适配器与数据绑定前将数据查询出来。

public class MyAdapter extends ArrayAdapter {

private int money;

private String address;

private String size;

private String orderid;

private int resourceId;

private String sendPerson;

private Context context;

private String url;

private ImageView img;

public MyAdapter(Context context,int textViewResourceId, List list){

super(context,textViewResourceId,list);

resourceId=textViewResourceId;

this.context=context;

}

@Override

public View getView(final int position, View convertView, ViewGroup parent) {

OrderList orderList=getItem(position);

View view;

final ViewHolder viewHolder;

if (convertView == null){

view =LayoutInflater.from(getContext()).inflate(resourceId,parent,false);

viewHolder = new ViewHolder();

viewHolder.pk_address = (TextView)view.findViewById(R.id.pk_address);

viewHolder.pk_size = (TextView)view.findViewById(R.id.pk_size);

viewHolder.pk_money=(TextView)view.findViewById(R.id.pk_money);

viewHolder.receiveimg=(ImageButton)view.findViewById(R.id.receiveimg);

viewHolder.icon=(ImageView)view.findViewById(R.id.icon);

view.setTag(viewHolder);

}else {

view=convertView;

viewHolder = (ViewHolder) view.getTag();

}

money = orderList.getMoney();

address = orderList.getAddress().toString();

orderid = orderList.getOrder_id().toString();

size =orderList.getPackage_size().toString();

sendPerson=orderList.getStuID_send().toString();

viewHolder.pk_address.setText("收货地址: "+address);

viewHolder.pk_size.setText("包裹大小: "+size);

viewHolder.pk_money.setText("酬金: ¥"+money);

viewHolder.receiveimg.setImageResource(R.drawable.receive);

MyAsyncTask imageTask=new MyAsyncTask(viewHolder.icon,context);

imageTask.execute(sendPerson);//通过调用execute方法开始处理异步任务.相当于线程中的start方法.

//给接单ImageButton设置监听事件

viewHolder.receiveimg.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

mitemListener.onRbtnClick(position);

mitemListener.getOrderID(orderid);

}

});

return view;

}

/**

* 图片按钮的监听接口

*/

public interface onItemRbtnListener {

void onRbtnClick(int i);

void getOrderID(String oid);

}

private onItemRbtnListener mitemListener;

public void setOnItemClickListener(onItemRbtnListener itemListener) {

this.mitemListener = itemListener;

}

class ViewHolder{

TextView pk_size;

TextView pk_money;

TextView pk_address;

ImageButton receiveimg;

ImageView icon;

}

class MyAsyncTask extends AsyncTask{

private ImageView imv;

private String imgurl;

private String id;

private Context context;

public MyAsyncTask(ImageView imv,Context context){

this.imv=imv;

this.context=context;

}

@Override

protected void onProgressUpdate(String... values) {

super.onProgressUpdate(values);

Log.v("xiancheng",values[0]);

Glide.with(context)

.load(values[0])

.into(imv);

}

@Override

protected Void doInBackground(String... params) {

id=params[0];

BmobQuery query1 = new BmobQuery<>();

query1.addWhereEqualTo("StuID", id);

query1.findObjects(new FindListener() {

@Override

public void done(List object, BmobException e) {

if (e == null) {

imgurl =object.get(0).getImageUrl();

publishProgress(imgurl);

}

else{

}

}

});

return null;

}

}

}

下面解释一下上述代码

AsyncTask是一个抽象类,通常用于被继承

需要指定以下三个泛型参数:

Params:启动任务时输入参数的类型

Progress:后台任务执行中返回进度值的类型

Result:后台执行任务完成后返回结果的类型

当调用imageTask.execute(sendPerson);时开始处理异步任务。

传入的是发布者的id。此参数被doInBackground方法接收,它的参数类型为Strings...代表是一个数组。

取出id查询出此id对应的头像图片地址,用publishProgress(imgurl)的方法更新imgurl的值,此方法调用后就会触发onProgressUpdate()方法,它的参数doInBackground()返回的结果,也就是图片的地址。

使用Glide加载图片。

Glide,是一个被google所推荐的图片加载库。

导入

在AndroidStudio上添加依赖

dependencies {

implementation 'com.github.bumptech.glide:glide:3.7.0'

implementation 'com.android.support:support-v4:23.2.1'

}

Glide.with(context).load(values[0]).into(imv);

context上下文 values[0]图片地址 imv 图片显示的对象

三、通过接口的参数传递信息

点击图片按钮后,要将此列的订单id传回到Activity中处理

public interface onItemRbtnListener {

void onRbtnClick(int i);

void getOrderID(String oid);

}

private onItemRbtnListener mitemListener;

getView中:

//给接单ImageButton设置监听事件

viewHolder.receiveimg.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

mitemListener.onRbtnClick(position);

mitemListener.getOrderID(orderid);

}

});

Activity中:

myAdapter.setOnItemClickListener(new MyAdapter.onItemRbtnListener() {

@Override

public void onRbtnClick(int i) {

Log.v("Helpothers", "点击了接单按钮" + i);

}

@Override

public void getOrderID(String oid) {

Log.v("Helpothers", "订单号:" + oid);

}

});

}

定义了一个接口,并用它初始化了一个实例,当点击图片按钮时,调用接口的两个方法,将position和订单id作为参数传入。如果一个方法的参数是接口类型,我们就可以将任何实现该接口的类的实例的引用传递给该接口参数,那么该接口参数就可以回调类实现的接口方法。

四、google滑动菜单

xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:app="http://schemas.android.com/apk/res-auto"

android:id="@+id/drawer_layout"

android:layout_width="match_parent"

android:layout_height="match_parent">

android:layout_width="match_parent"

android:layout_height="match_parent">

android:id="@+id/toolbar"

android:layout_width="match_parent"

android:layout_height="?attr/actionBarSize"

android:background="?attr/colorPrimary"

android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"

app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>

android:layout_width="match_parent"

android:layout_height="match_parent"

android:id="@+id/nav_view"

android:layout_gravity="start"

app:menu="@menu/nav_menu"

app:headerLayout="@layout/nav_header"/>

DrawerLayout中放置了两个直接子控件:

第一个子控件是FrameLayout,用于作为主屏幕中显示的内容。

第二个子控件这里使用了一个NavigationView,用于作为滑动菜单中显示的内容。

google提出了meteral design这样的一个设计理念之后,提供给用户官方的侧边栏的控件,就是NavigationView。

引入DesignSupport库

implementation 'com.android.support:design:27.1.1'

作为DrawerLayout的第二个子控件

android:id="@+id/nav_view"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:layout_gravity="start"

app:menu="@menu/nav_menu"

app:headerLayout="@layout/nav_header"/>

NavigationView包含两个部分:menu,headerLayout

headerLayout

android:layout_width="match_parent"

android:layout_height="180dp"

android:padding="10dp"

android:background="@drawable/headerlayout">

可写任意布局,此处经常被用于展示用户信息

注意height写成180dp比较合适

menu

android:id="@+id/nav_tv"

android:icon="@drawable/ic_action_tv"

android:title="TV"/>

android:id="@+id/nav_song"

android:icon="@drawable/ic_action_song"

android:title="SONG"/>

android:id="@+id/nav_word"

android:icon="@drawable/ic_action_word"

android:title="WORD"/>

menu就是普通menu的写法,但要注意这里的group标签表示该组中的item只能单选

设置菜单中的item的监听事件

NavigationView navigationView=(NavigationView)findViewById(R.id.nav_view);

navigationView.setCheckedItem(R.id.nav_tv);

navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener(){

@Override

public boolean onNavigationItemSelected(MenuItem item){

mDrawerLayout.closeDrawers();

return true;

}

});

setCheckedItem(int id)设置默认选中项

setNavigationItemSelectedListener()设置监听器

五、使用RecylerView的方法在listview中嵌套横向listview

my_publish.xml中

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="#f5f5f5"

android:paddingLeft="15dp"

android:paddingRight="15dp"

android:paddingTop="20dp"

android:divider="#00000000"

android:dividerHeight="14dp"

android:id="@+id/mypublis_list_view">

mypublish_listview_item.xml中

android:orientation="vertical" android:layout_width="match_parent"

android:layout_height="wrap_content"

android:padding="20dp"

android:elevation="2dp"

android:background="@drawable/myrect" >

android:id="@+id/mp_orderid"

android:layout_width="wrap_content"

android:layout_height="25dp"

android:text="订单号"

android:textColor="#757575"

android:textSize="14sp" />

android:layout_width="match_parent"

android:layout_height="2dp"

android:layout_marginRight="15dp"

android:background="#f5f5f5" />

......

......

android:focusable="false"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:id="@+id/list_two">

mypublish_listview_item_item.xml中

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:orientation="horizontal">

android:layout_width="35dp"

android:layout_height="35dp"

android:id="@+id/stu_receive"

android:scaleType="center"

android:layout_margin="5dp"/>

适配器中:

找到RecyclerView

viewHolder.recyclerView=(RecyclerView)view.findViewById(R.id.list_two);

LinearLayoutManager lm=new LinearLayoutManager(mcontext);

lm.setOrientation(LinearLayoutManager.HORIZONTAL);

viewHolder.recyclerView.setLayoutManager(lm);

设置布局管理器方法,实现RecylerView布局里面的内容显示方式;

LinearLayoutManager:线性布局管理器

使用布局显示关键字LinearLayoutManager.HORIZONTAL

横向listView的适配器

viewHolder.recyclerView.setAdapter(new MyHorizontalAdapter(orderid,mcontext));

package com.xiaoding.finalproject;

import android.content.Context;

import android.content.Intent;

import android.graphics.Bitmap;

import android.graphics.BitmapFactory;

import android.os.AsyncTask;

import android.support.annotation.NonNull;

import android.support.v7.widget.RecyclerView;

import android.util.Log;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.widget.ArrayAdapter;

import android.widget.ImageView;

import android.widget.TextView;

import com.bumptech.glide.Glide;

import java.io.IOException;

import java.util.List;

import cn.bmob.v3.BmobQuery;

import cn.bmob.v3.exception.BmobException;

import cn.bmob.v3.listener.FindListener;

import okhttp3.Call;

import okhttp3.Callback;

import okhttp3.OkHttpClient;

import okhttp3.Request;

import okhttp3.Response;

import static cn.bmob.v3.b.From.e;

public class MyHorizontalAdapter extends RecyclerView.Adapter{

private List list;

private View view;

private String orderid;

private Context context;

private ImageView receiverImg;

protected String[] receive_stuid=new String[100];

MyHorizontalAdapter(){}

MyHorizontalAdapter(String orderid,Context context){

this.orderid=orderid;

this.context=context;

}

@Override

public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

view=View.inflate(parent.getContext(),R.layout.mypublish_listview_item_item,null);

ViewHolder holder=new ViewHolder(view);

return holder;

}

@Override

public void onBindViewHolder(@NonNull ViewHolder holder, final int position) {

MyAsyncTask myAsyncTask=new MyAsyncTask(holder.tv,context);

myAsyncTask.execute(orderid,""+position);

receiverImg=(ImageView)view.findViewById(R.id.stu_receive);

receiverImg.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View view) {

Log.v("dgc","点击了子listview的item"+receive_stuid[position]);

Intent intent = new Intent();

intent.putExtra("receiverid",receive_stuid[position]);

intent.putExtra("orderid",orderid);

Log.v("dgc","receiverid"+receive_stuid[position]);

intent.setClass(context,ReceiverInfo.class);

context.startActivity(intent);

}

});

}

@Override

public int getItemCount() {

return 10;

}

public class ViewHolder extends RecyclerView.ViewHolder{

ImageView tv;

public ViewHolder(View itemView){

super(itemView);

tv=(ImageView) itemView.findViewById(R.id.stu_receive);

}

}

class MyAsyncTask extends AsyncTask {

private ImageView imv;

private Context context;

private String imgurl;

private int position;

public MyAsyncTask(ImageView imv,Context context){

this.imv=imv;

this.context=context;

}

@Override

protected void onProgressUpdate(String... values) {

super.onProgressUpdate(values);

Log.v("xiancheng",values[0]);

Glide.with(context)

.load(values[0])

.into(imv);

}

@Override

protected Void doInBackground(String... params) {

position=Integer.parseInt(params[1]);

Log.v("dgc",position+"");

BmobQuery query = new BmobQuery<>();

query.addWhereEqualTo("order_id", params[0]);

Log.v("dgc","orderid:"+params[0]);

query.findObjects(new FindListener() {

@Override

public void done(List object, BmobException e) {

if (e == null) {

receive_stuid[position] =object.get(position).getStuID_receiveorder();

Log.v("dgc",receive_stuid[position]);

BmobQuery query1 = new BmobQuery<>();

query1.addWhereEqualTo("StuID", receive_stuid[position]);

query1.findObjects(new FindListener() {

@Override

public void done(List object, BmobException e) {

if (e == null) {

imgurl=object.get(0).getImageUrl();

Log.v("dgc",imgurl);

publishProgress(imgurl);

}

else{

Log.v("dgc","127:"+e.toString());

}

}

});

}

else{

Log.v("dgc","133:"+e.toString());

}

}

});

return null;

}

}

}

啊 怎么解释

RecyclerViewAdapter.class :继承RecyclerView.Adapter后,会重写三个方法:

onCreateViewHolder()方法,负责承载每个子项的布局。它有两个参数,其中一个是 int viewType;

onBindViewHolder()方法,负责将每个子项holder绑定数据。俩参数分别是RecyclerView.ViewHolder holder, int position;

getItemCount()返回有多少项

下面的稍微复杂,还是用异步的方法,将订单id传入和所点击的position传入,通过查询接单表找到与传入订单id相同的列,取出接单人id,再用此接单人id在用户信息表中查询头像图片地址,用Glide加载。

还有一些比较简单的功能就不写了。

六、一些样式上的技巧

1、ToolBar代替Actionbar在AppCompatActivity的使用

需要给Activity设置主题 无Actionbar即可

android:theme="@style/Theme.AppCompat.Light.NoActionBar">

Toolbar toolbar=(Toolbar)findViewById(R.id.toolbar);

setSupportActionBar(toolbar);

mDrawerLayout=(DrawerLayout)findViewById(R.id.drawer_layout);

NavigationView navView=(NavigationView)findViewById(R.id.nav_view);//获取滑动菜单实例

ActionBar actionBar=getSupportActionBar();//获取ActionBar实例

if(actionBar!=null){

actionBar.setDisplayHomeAsUpEnabled(true);

actionBar.setHomeAsUpIndicator(R.mipmap.ic_menu);

}

最后两行是把导航栏的返回图标替换成菜单图标

2、NavigationView中获取对象要通过以下步骤

NavigationView navigationView = findViewById(R.id.nav_view);

View view = navigationView.getHeaderView(0);

headimg=(ImageView)view.findViewById(R.id.icon_img);

3、列表项之间的空格

实际上是把分割线的颜色设置成透明,并给一定高度,看上去就像设置了一个间距

android:divider="#00000000"

android:dividerHeight="14dp"

4、矩形的圆角和阴影

自己写一个放在drawable里面,在设置样式的地方用background属性调用

android:background="@drawable/myrect"

android:shape="rectangle">

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值