kuaiyijia工作日志 - yunfanfan/Notes GitHub Wiki

kuaiyijia开发

搁置任务清单

  • Dialog标题

12.1

开始二级页面UI的制作,首先梳理一遍有哪些功能点。

顶栏:更换当前网点

351638324320_.pic

选择弹出框中的网点后,右上方的地址会改变,左上方是单位名。

一个单位有多个网点。也就是说这里是更换“当前单位的网点”。

(部分未完成)这里要实现一个底部弹出菜单栏

参考:Android中实现底部弹出菜单栏_xys199719的博客-CSDN博客_android 底部弹出菜单

Toast toast=Toast.makeText(getApplicationContext(), "默认的Toast", Toast.LENGTH_SHORT); 

getApplicationContext()可获取当前context

遇到了报错,参考Dialog(四)——报错Unable to add window -- token null is not for an application_谷哥的小弟-CSDN博客

不可使用Builder builder=new Builder(getApplicationContext());

应该使用Builder builder=new Builder(MainActivity.this);

故将前面的getApplicationContext()全部换成MainActivity.this

成功启动!

还需要给dialog加个标题

mChangNetPointDialog.setTitle("更换当前网点");

没有作用,未显示。搁置。

(未完成)点击按钮

这里点击更换网点地点的按钮之后需要更改数据库中的值。

搜索栏

搜索运单号,在数据库中查询运单号。

点击Search按钮会在数据库中查询相应运单号。

扫码

扫的什么码?

问题

I/Choreographer: Skipped 28 frames!  The application may be doing too much work on its main thread.

只在测试手机魅族18上用摄像头扫码时会出现。

功能1:新运单

361638324321_.pic

点击新运单后,会选择网点,然后进入“新增运单”页面填写表单:

371638324321_.pic

第一行的目标网点可以点击进行更换。

功能2:发运

进入发运管理

功能3:收货

进入收货管理

功能4:新退单

填写退单表单

381638324322_.pic

功能5:取货

进入取货管理

11.30

开始实现无限轮播,以及添加图片

添加图片

adapter读取图片资源,把之前的android.R.color.holo_orange_light改成图片地址R.drawable.banner_index_1就好了。

public VpAdapter(Context context) {
        mContext = context;
        if (backgrounds == null) {
            backgrounds = new ArrayList<>();
            backgrounds.add(R.drawable.banner_index_1);
            backgrounds.add(R.drawable.banner_index_2);
            backgrounds.add(R.drawable.banner_index_3);
            backgrounds.add(android.R.color.holo_orange_light);
            backgrounds.add(android.R.color.holo_purple);
        }
    }

无限轮播

学习笔记:使用ViewPager2实现简易轮播图 - 极客分享

按照ViewPager2打造Banner轮播图 - 掘金来实现

registerOnPageChangeCallback如何使用

终于找到一个讲学不动也要学! ViewPager2新特性 - SegmentFault 思否

附上一段kotlin和java代码对比

viewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                super.onPageScrolled(position, positionOffset, positionOffsetPixels);
            }

            @Override
            public void onPageSelected(int position) {
                currentPosition = position;
            }

            @Override
            public void onPageScrollStateChanged(int state) {
                super.onPageScrollStateChanged(state);
            }
        });
bannerVp.registerOnPageChangeCallback(object :
    ViewPager2.OnPageChangeCallback() {
    override fun onPageSelected(position: Int) {
        currentPosition = position
    }
    override fun onPageScrollStateChanged(state: Int) {
        //只有在空闲状态,才让自动滚动
        if (state == ViewPager2.SCROLL_STATE_IDLE) {
            if (currentPosition == 0) {
                bannerVp.setCurrentItem(adapter.itemCount - 2, false)
            } else if (currentPosition == adapter.itemCount - 1) {
                bannerVp.setCurrentItem(1, false)
            }
        }
    }
})

分析下面这段代码:

if (state == ViewPager2.SCROLL_STATE_IDLE) {
                    Log.d("getItemCount()=", Integer.toString(adapter.getItemCount()));
                    viewPager2.setCurrentItem(adapter.getItemCount() -2, false);
                } else if (currentPosition == adapter.getItemCount() - 1) {
                    Log.d("getItemCount2()=", Integer.toString(adapter.getItemCount()));
                    viewPager2.setCurrentItem(1, false);
                }
D/currentpage: 0 //刚进app第一个界面,position为0
D/currentpage: 1 //手动向右滑动,position到了1
D/getItemCount()=: 5 //进入了第一个if,执行了setCurrentItem(5-2)
D/currentpage: 3 //页面一共有5个,从0开始,分别是0,1,2,3,4
D/currentpage: 3 //页面3,0和3页面是一样的,1和4是一样的

之前代码基本是没问题的,就是第一个if条件写错了

按照这个表格来的话是完全没有问题的:

位置 处理
currentPosition == 0 setCurrentItem(adapter.itemCount - 2, false)
currentPosition == adapter.itemCount - 1 setCurrentItem(1, false)
if (currentPosition == 0) {
	viewPager2.setCurrentItem(adapter.getItemCount() -2, false);
	} else if (currentPosition == adapter.getItemCount() - 1) {
		viewPager2.setCurrentItem(1, false);
}

自动滑动

//自动连播
        Thread mLoop = new Thread(new Runnable() {
            @Override
            public void run() {
                int currentItem = viewPager2.getCurrentItem();
                viewPager2.setCurrentItem(currentItem + 1);
                viewPager2.postDelayed(this, 2500);
            }
        });
        viewPager2.postDelayed(mLoop, 2500);

照这样写会有个小bug,没有找到原因,运行状态如下:

D/currentpage: 0
D/banner:: onPageScrollStateChanged: 到第0页了,设置page为3
D/currentpage: 3
D/currentpage: 1
D/currentpage: 3
D/currentpage: 3
D/currentpage: 3
D/currentpage: 3
D/currentpage: 3
D/currentpage: 3
D/currentpage: 3
D/currentpage: 3
D/currentpage: 4

到第四页了,没有促发连播,需要手动往右划一下,才能继续运行。

既然不会自动促发,那我就来手动促发,添加一段if判断

if (currentItem == 4) {
   Log.d(TAG, "thread: 到第4页了,设置page为1");
   viewPager2.setCurrentItem(1, false);
}

运行完美!

11.29

变量名

边框 - CODELF

Android在Button按钮上同时显示文字和图片

Android在Button按钮上同时显示文字和图片_程序员-CSDN博客

去掉EditText下划线

android:background="@null"

Layout边框

Android---给Linearlayout设置边框+弧度角_Yo.o-CSDN博客_linearlayout 边框

imagebutton

Android ImageButton 图片按钮 - Android 基础教程 - 简单教程,简单编程

控件背景透明

用android系统的透明效果

android:background="@android:color/transparent" 

轮播图

昨天轮播图实现失败,今天重新学习了viewpage2,参考ViewPager 2 使用讲解 - 简书

梳理一下思路,首先有一个Activity,以及它对应的layout,这个layout中放置了一个viewpager2的view,代码如下:

<androidx.viewpager2.widget.ViewPager2
        android:id="@+id/vp_h"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

然后在Activity中要初始化一个Adapter,并且把这个Adapter设置给这个viewPager2,代码如下:

ViewPager2 viewPager2 = findViewById(R.id.vp_h);
HorizontalVpAdapter adapter = new HorizontalVpAdapter(this);
viewPager2.setAdapter(adapter);

下面就要完成相对应的Adapter,代码如下:

public class HorizontalVpAdapter extends RecyclerView.Adapter<HorizontalVpAdapter.HorizontalVpViewHolder> {
    private List<Integer> backgrounds;
    private Context mContext;

    public HorizontalVpAdapter(Context context) {
        mContext = context;
        if (backgrounds == null) {
            backgrounds = new ArrayList<>();
            backgrounds.add(android.R.color.holo_blue_bright);
            backgrounds.add(android.R.color.holo_red_dark);
            backgrounds.add(android.R.color.holo_green_dark);
            backgrounds.add(android.R.color.holo_orange_light);
            backgrounds.add(android.R.color.holo_purple);
        }
    }
    @NonNull
    @Override
    public HorizontalVpViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return new HorizontalVpViewHolder(LayoutInflater.from(mContext).inflate((R.layout.item_h_v), parent, false));
    }

    @SuppressLint("SetTextI18n")
    @Override
    public void onBindViewHolder(@NonNull HorizontalVpViewHolder holder, int position) {
        holder.mTextView.setText("第  " + (position + 1) + " 界面");
        holder.mLinearLayout.setBackgroundResource(backgrounds.get(position));
    }

    @Override
    public int getItemCount() {
        if (backgrounds == null) {
            return 0;
        }
        return backgrounds.size();
    }
    class HorizontalVpViewHolder extends RecyclerView.ViewHolder {
        LinearLayout mLinearLayout;
        TextView mTextView;

        HorizontalVpViewHolder(@NonNull View itemView) {
            super(itemView);
            mLinearLayout = itemView.findViewById(R.id.ll_h_v);
            mTextView = itemView.findViewById(R.id.tv_hv);
        }
    }
}

这其中涉及到了一个新的layout,我猜是用在viewpager2中显示具体不同内容的。

新的layout代码如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/ll_h_v"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:id="@+id/tv_hv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:textColor="#ffffff"
        android:textSize="16sp" />

</LinearLayout>

基本结构就完成了。

11.28

实现第一行的按钮

实现下面的轮播图,参考:Android 轮播图实现(新手易懂)_请叫我海贼王p的博客-CSDN博客_android轮播图实现

11.26

11.26开始着手App的界面重构。


以下是上半年的工作笔记

总工作安排

  1. 快捷收货
    • 扫描订单
    • 运价
  2. 装车码模块
    • 查询车辆
    • 生成装车码
    • 扫码装车
    • 扫码卸货
  3. 任务车辆
    • 扫码发车
    • 状态反馈

2.26

25号把数据操作代码写好了,除了数据查询部分。

26号开始写数据查询部分,数据处理都在database类里面,但是查询需要把查询结果返回回来。我就把返回值改成了ResultSet,这是一个结果集,封装了使用JDBC进行查询的结果,所以我需要的数据就在这个类里面。

问题1:(已解决)

现在数据是可以取出来了,测试也都没有问题,但是一放到我的代码里面就报错:

“'java.sql.Statement java.sql.Connection.createStatement()' on a null object reference”

解决办法:Android4.0以后不支持在主线程进行耗时操作,因此,如果设备是4.0版本以上的,要新开一条线程操作数据库。

最后开了一个线程就解决了!

现在能拿到数据了,可以开始着手生成装车码了。

问题2:(已解决)

车牌等数据是从子线程中得到的,但是setText不能在子线程中执行,如果把setText拿出来,又会导致数据消失。

解决办法:好像要用到线程间通信。

“Handler的创建方式有两种:一个是在主线程中创建,一个是在普通工作线程中创建,两种创建方法是不一样的。Handler在哪个线程中创建,那该线程就负责接收和处理消息,其它的线程只能发送消息。”

谁要收消息,谁就创建。

3.1 周一

问题1:

handleMessage的代码为什么最后执行(相较于点击事件的代码)?

问题2:(已解决)

sorry, the android camera encountered a problem. You may need to restart the device.

解决:“For Android 6+, because of the "permission" issue, If you got the message "Sorry, the camera encountered a problem. You may need to restart the device.", go to Settings - Apps - find "your app name" - select Permissions and switch on "Camera”.”

今日工作总结:

  1. 解决了线程间数据传递的问题
  2. 可根据字符串生成二维码
  3. 可打开相机扫描二维码。

3.2 周二

资料网址总结——云凡

  1. (1条消息) android 连接SQL Server数据库并进行数据操作_amberoot's Space-CSDN博客
  2. (1条消息) android直接链接sqlserver数据库_马腾蛟的博客-CSDN博客_android访问sqlserver数据库
  3. Java JDBC入门之四:通过ResultSet执行查询操作并处理结果集_码农回顾-CSDN博客
  4. JDBC那些事(二)——查询结果集_ResultSet_JUSTIN的博客-CSDN博客_jdbc遍历结果集
  5. Android线程间通信机制 - 简书
  6. android Handler Message传递参数_meixi_android的博客-CSDN博客
  7. Androidstudio中添加jar包的方法_zhenghongwu的博客-CSDN博客

扫码装车模块

业务逻辑不是很明白,文档中无任何描述。根据这个流程图,为什么扫描后如果不是装车码,就要去扫描订单码?

image-20210302161516524

快捷收货模块

和扫码卸货的区别?是不是卸货是针对货运网点之间的,而收货是针对最后一站修理厂的?

运价页面的功能描述:“(1) 用户扫描一个订单码后,进入选择运价页面,选择对应运价,确认。(一个订单可能有多个商品条码,扫描每一个都需要进入运价页面,但如果没有扫描全部商品条码,会进入扫码不全页面,此功能需熟悉完后再进行开发)”

用户扫描的到底是订单码还是商品条码?并且选择运价之后需要修改数据库中什么表项?

强烈要求把需求文档中的“相关数据库及其字段”这一项补齐。

3.3 周三

开始使用vivo x20真机进行调试

报错1(已解决)

![屏幕快照 2021-03-03 下午20.05.56 下午](/Users/yunfan/Desktop/屏幕快照 2021-03-03 下午20.05.56 下午.png)

定位错误在线程内部sendMessage(msg)的地方。

根据解决Handler发送消息时:this message is already in use_xu_Melon的博客-CSDN博客所说,

报错的信息是指:发送的message正在消息队列中,不能被使用。

其实就是当我们想多次发送消息时,不能使用同一个消息的意思,所以解决的方法就是再次发送的时候重新获取一个新的消息.

检查自己的代码,发现我把sendMessage(msg)放在了循环内部,估计是这个原因,被运行了多次,所以消息就冲突了,所以我把这条语句拿出来放到循环外面,整个程序就正常了。

继续开发扫码相关功能

扫码成功界面

找到代码中显示“渝A66666”相关变量

由于之前直接导入的别人封装好的arr扫码模块,导致此处无法自己更改相关代码。现在回到上一步,重新添加扫码功能。

开始参考yuzhiqiang1993/zxing: 基于zxing的扫一扫,优化了扫描二维码速度,集成最新版本的jar包(zxing-core.jar 3.3.3),集成简单,速度快,可配置颜色,还有闪光灯,解析二维码图片,生成二维码等功能,添加扫码功能。

安装成功,可以获取扫码结果。

开始编写扫码装车模块

搬运人员先扫描装车码,与车辆绑定

疑问:搬运人员为什么要和车辆绑定?以什么形式绑定。

答:搬运人员相当于一条线,连接车辆和车辆需要运送的商品。

在bindDialog中点击确认后,还需添加扫码每个商品条形码的代码。

问题1:

未在数据库中找到货物与车辆绑定的相关数据表。

3.4 周四

开始开发扫码发车功能

问题1

绑定司机和车辆时,需要添加司机id,司机id如何获取?

问题2(已解决)

Java 向数据库中输入 datetime类型数据

参考:Java 向数据库中输入 datetime类型数据_ChaoQun-CSDN博客_数据库datetime输入格式

插入数据的新方法

之前每次插入数据都是把整个句子写死了,今天突然要插入变量,再去手动写value字符串就很麻烦。在网上发现了一段代码可以用?填充。

Date date = new Date();  
Timestamp timeStamp = new Timestamp(date.getTime()); 
 sql= "insert into flowmeter2(total,std_flow,temp,press,time) values(?,?,?,?,?)";   
        try {  
            PreparedStatement ps = connection.prepareStatement(sql);  
            ps.setString(1, total);  
            ps.setString(2, std_flow);  
            ps.setString(3, temp);  
            ps.setString(4, press);  
            ps.setTimestamp(5, timeStamp);  
            ps.executeUpdate();  
            System.out.println("添加成功!");  
            connection.close();  

但是必须要在加入数据的时候指定数据类型,故放弃此方法。

之后发现正是由于需要指定数据类型,所以还必须用此方法。

所以不能把数据库操作写在database类中,而是直接在需要的地方进行数据库连接操作。

Connection conn = database.getSQLConnection();
try {
    PreparedStatement ps = conn.prepareStatement(sql);
    ps.setInt(1,1);
    ps.setString(2,ti_rq);
    ps.setInt(3,mResultScan);
    ps.setInt(4,1);
    ps.setTimestamp(5,timeStamp);
    ps.executeQuery();
    conn.close();
} catch (SQLException throwables) {
    throwables.printStackTrace();
}

最后要获取数据操作之后成功与否的状态,通过

ps.executeUpdate()//它会返回数据库中所操作的数据行数

如果它返回值为1就表明数据操作成功,绑定成功。

今日工作总结

扫码发车功能基本开发完毕,可以绑定司机与车辆,并且显示绑定成功页面。

明天开始开发状态反馈功能。

3.8 周一

状态反馈

数据库中需要修改运输记录表(XS_TRAN_INFO)中的RESULTMSG路途故障反馈说明。

开发完毕,能够正常更新数据库,并返回结果。

扫码卸货

因为没有提供具体的订单表,所以此功能搁置

快捷收货模块——扫描订单

首先,扫码,然后查询结果是否是订单二维码。

如果是,就执行数据库操作,接单,并且进入选择运价页面,新建activity,跳转。

如果不是,就提示无此订单号

快捷收货模块——选择运价

扫码商品条码,选择对应运价。

问题1

通过**货运运价表(PUB_FTRANPRICE)**中的什么表项来选择运价?

3.6.2.3中的页面设计有包装的规格,是通过货运包装类ID来选择吗?

image-20210308145435223

3.9 周二

扫码卸货

关于订单表的说明,要登录他们的saas系统。上面有数据字段说明

明天后天直接用之前的旧mysql数据库表段来开发。

3.11 周四

完善扫码卸货

功能描述:收货人扫描订单上的二维码,进行绑定,同时更改订单状态

卸货是网点签收上个网点来的货物,扫码卸货后,货物的状态更改为”XXX网点 已到货”。

Mysql数据库:

[email protected] 端口3306 用户root 密码123456Abc

订单二维码根据表orders中表项order_number生成

商品条码储存在order_huowu_code中,并且在表order_huowus中的code_path与订单二维码绑定,一个订单二维码对应多个商品条码。

订单状态:'0新建 1已接单(被抢单)2 已取货 3送货中 4到货 5完成 6异常 100取消'

修改订单状态:表orders中表项order_status设置为5

问题1:

突然发现之前搜索车牌的时候未做判空处理,也就是说如果没有在数据库中找到相应车牌号,应该怎么做。

解答:根据rs.isBeforeFirst方法

当 ResultSet 为非空时,其游标指向第一条记录前面,若为空时由于不存在第一条记录,所以这时候游标也无法向指第一条记录前面

注意:

主线程不能做耗时操作,子线程中不能做更改UI操作,子线程需要通过handler才能来做更改UI的相关操作。

3.12 周五

完成扫码卸货操作。

扫码装车模块

3.3

搬运人员相当于一条线,连接车辆和车辆需要运送的商品。

在bindDialog中点击确认后,还需添加扫码每个商品条形码的代码。

  1. 扫描装车码
  2. 判断是否绑定当前车辆
  3. 再去数据库查询是否是装车码
  4. 就去执行搬运人员和车辆的绑定操作
  5. 依次扫描每个商品条形码,绑定搬运人员和货物
    1. 先把商品条码insert在order_huowu_code
    2. 然后update表order_huowus中的PORTER_ID

完成功能,未测试。

3.25 周四

把之前的代码逻辑过一遍,改一下一些遗留的小问题。

装车码模块

搜索还缺少“模糊搜索”,等优优回来了看看。

之前写扫码功能的时候测试加了一个button,现在直接注释掉其点击事件。

点击确认,应该执行打印操作。此处还没开发。

扫码发车

注意点击扫码发车时,先去数据库查询是否有此装车码。

在xs_tran_info表中插入数据时,实际的司机id需要之后单独获取,并且需要解决第一个参数自增的方法。

目的地在线路到站表(PUB_LINES_D) 中 L_END 到站

完成了一个从数据库中获取单个数据,并且转换成message的方法

使用范例如下

import com.example.kuaiyijia.ui.utility;
Message msgInfo = new Message();
mHandler.sendMessage(utility.getInfo(msgInfo,4,"PUB_VEHICLE","V_ID",mResultScan,"mV_no", "V_NO"));

明天应该完成一个变量名列表

3.26 周五

扫码发车步骤

  1. 注意点击扫码发车时,先去数据库查询是否有此装车码。
  2. 如果是装车码,就绑定司机和车辆,向xs_tran_info插入数据,线路id以及司机id从何处获取?
  3. 绑定成功后,更新界面车牌目的地数据
    1. 根据运输记录TI_ID来查询路途故障反馈说明RESULTMSG

(突然意识到,app还缺少根据对于登录人员获取个人基本信息的部分)

完成功能。

扫码装车

CREATE TABLE [dbo].[PUB_CARPORTER] (
  [id] bigint IDENTITY(1,1),
  [V_ID] bigint NOT NULL,
  [PORTER_ID] int  NULL,
  CONSTRAINT [PK__PUB_CARP__3213E83F71D1E811] PRIMARY KEY CLUSTERED ([id])
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)  
ON [PRIMARY]
)  
ON [PRIMARY]
GO

ALTER TABLE [dbo].[PUB_CARPORTER] SET (LOCK_ESCALATION = TABLE)

改了与huowu有关的几个表的描述,有关主键自增。

发现变量Request_code_scan好像是用来控制不同的扫码过程的。

步骤五还要再认真思考一下。

3.30 周二

变量Request_code_scan确实是用来控制不同的扫码过程

扫码装车部分,暂时按照之前步骤来做。

5.2中“然后update表order_huowus中的PORTER_ID”,表中还需要一些测试数据。

⚠️ **GitHub.com Fallback** ⚠️