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

先上图了解基本功能

注册

登录

主界面

帮我取件

帮人代取

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

滑动菜单

我的发布

可选择接单人

接单人信息

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

我的接单

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

下面开始介绍用到的方法

在开发中遇到的大坑: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">

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

  1. 智能信用卡还款软件是什么?和传统代还平台有什么区别?

    截止2018年第三季度,目前我国信用卡累计发卡量已接近10亿张.卡均授信额度为1.7万元,中国城市近10亿消费入口将催生世界上最大的信用卡消费市场.而大约有百分之40到百分之60的信用卡用户不能如期还 ...

  2. 【安卓大作业】Android Studio学校图书管理系统

    [安卓大作业]Android Studio学校图书管理系统 一.界面展示 二.功能介绍 图书馆介绍.查看上架新书.借阅排行榜 学生端.图书借阅.管理员端.图书管理等 三.项目结构 四.关键代码展示 ( ...

  3. 汽车中控屏显示com点android,老车遇上安卓大屏导航中控的坑

    老车遇上安卓大屏导航中控的坑 2020-11-22 23:20:11 2点赞 0收藏 3评论 起因 事发在前天,我开着13款经典福去加油,加完之后打火,发现用了6年的飞歌车机不亮了.本来以为重新打火就 ...

  4. android过渡动画软件,安卓P过渡动画下载-安卓P过渡动画 v1.0_手机乐园

    软件简介 安卓P过渡动画是一款xp模块,免费的而且安装包也是超级的小,操作起来比较方便,可以从Android P-jfy中进行模块的分离,通过进行定义每一个关键帧的元素属性值进行复杂动画效果的轻松实现 ...

  5. 软件项目管理大作业_案例|P6软件在水电项目施工管理中的应用

    P6 广泛应用于国际大型工程项目中,利用先进的项目管理软件来进行项目管理显得尤为重要.今天这篇文章以美纳斯水电项目为例,从项目施工角度,介绍P6 项目管理软件进行项目施工技术管理,包括进度控制.技术文 ...

  6. android主流手机测试,硬件测试哪家强?安卓手机跑分软件横评

    现在手机一款接着一款出,产品的噱头也是五花八门,很多朋友抱怨对手机不是很懂,因此在选择购买哪款手机的时候经常拿不定注意,害怕买了性价比不高的手机.那么,我们如何在没有那么多专业知识,对手机不慎了解的情 ...

  7. android 解压rar5,rar解压软件安卓中文

    rar解压软件安卓中文专门为需要快速解压自己文件的小伙伴准备的好用的实用工具,帮助你快速能处理自己的文件信息,支持多种格式解压,相信不少的用户都会喜欢,赶紧下载最新的rar解压软件体验吧! 软件介绍 ...

  8. 安卓手机主题软件_安卓必备APP大盘点:10款软件让你的手机脱胎换骨

    相信许多使用安卓手机的朋友们对系统都多多少少有些怨念,流氓软件层出不穷.后台占用损耗严重.通知信息日益激增.拍照软件滤镜丑爆等一系列问题仿佛一块块心病常年压得安卓用户喘不过气来,不少安卓党也因此转投苹 ...

  9. android手机改车载,到底手机导航还是车载导航好,我选择在车上加装安卓大屏...

    到底手机导航还是车载导航好,我选择在车上加装安卓大屏 2017-06-12 18:38:38 52点赞 66收藏 74评论 这几年随着国民经济和技术水平的提升,汽车早已不是以前那种高不可攀的奢侈品,不 ...

最新文章

  1. iOS - OC Foundation 框架
  2. sublime text3 运行lua_[电脑常识] 用这4个系统垃圾清理软件,让电脑操作系统运行如飞 !...
  3. 右键 Dos在这里 删除
  4. python中模块sys与os的一些常用方法
  5. MongoDB学习笔记三:查询
  6. 【从零之三(更)】自定义类中调用讯飞语音包错误解决办法
  7. (dijkstra记录路径)find the longest of the shortest
  8. PyCharm编辑器的安装
  9. CPU合并写缓冲区简介
  10. VS2010编译驱动程序
  11. http发送16进制报文_图解HTTP 第三章HTTP报文内的HTTP信息
  12. 万能五笔2005输入法平台6.46版---试用手记
  13. 呼吸机吸气触发:压力触发与流量触发
  14. 工作说明书(SOW)
  15. 以生活中的例子快速理解十个设计模式
  16. ctf——逆向新手题目8 (logmein) WP
  17. 三维分子模型软件PyMOL
  18. Android之APP跳转权限设置界面
  19. CDN加速的四大解决方案
  20. 手把手建项目 PrimeNG安装使用

热门文章

  1. 5-随机抓取易烊千玺置顶100万+转发微博的转发数据,并分析真假粉丝比例
  2. 语言文字工作调查问c卷(中学生),中小学生语言文字规范化问题分析语言文字规范化知识学生问卷...
  3. 华为如何打造智能终端的有趣灵魂?(上)
  4. golang 模板引擎 html,Golang模板引擎快速入门教程
  5. shell脚本之数组,冒泡排序算法
  6. docker制作mysql5.7镜像详解
  7. 【算法】随机数生成器
  8. 中电金信源启小程序开发平台 赋能金融+业务生态共享共建
  9. Windows 本地安全策略和本地组策略
  10. 云和数据第六届中国创业者大会英雄云集 继续点燃创业者心中热火