上门洗车APP --- Android客户端开发 之 项目结构介绍

前言

虽然公司项目较紧,但还是抽出时间给大家继续更新。     o_O"~ 欢迎大家的关注,很高兴和大家共同学习。前面给大家分享了项目中的以下内容:

上门洗车APP --- Android客户端开发 前言及业务简介

上门洗车APP --- Android客户端开发 之 网络框架封装介绍(一)

上门洗车APP --- Android客户端开发 之 网络框架封装介绍(二)

之前有很多朋友私信过来说想打包一份源码学习,由于本项目也是还在开发中,进度不是很快,后台那边的一系列接口需要调试,自己也是时间精力有限,还请朋友见谅。本篇博文给大家介绍项目的  整体目录结构,界面开发、项目中所使用的  自定义控件、技术点 等,同时也会打包一份目前最新的源码供感兴趣的朋友学习。

关于项目目录结构

首先我们来看下项目的目录结构,给大家做一些简单的介绍:

                  

由于目录过多,我们分了两张图展示,先对源码包的管理进行介绍:

org.gaochun.activity  -------> 管理Activity

org.gaochun.adapter -------> 通用万能Adapter

org.gaochun.android.http  -------> Android-Async-Http框架

org.gaochun.android.http.manager  -------> 通用数据管理(常量、URL、网络请求 等)

org.gaochun.android.http.network -------> 自定义回调接口

org.gaochun.android.http.request -------> 请求参数管理

org.gaochun.model -------> 实体Bean管理

org.gaochun.parser -------> 解析接口及抽象解析器管理

org.gaochun.parser.impl -------> 解析器管理

org.gaochun.receiver -------> 监听推送消息的Receiver

org.gaochun.ui -------> 标题栏及Application管理

org.gaochun.utils  -------> 常用工具类

org.gaochun.widget -------> 自定义控件管理(AlertDialog、圆形ImageView、带声音的Toast等)

部分技术点

有木有感觉层次还是比较清晰的呢?好了,不扯淡!给出了这些包中各自的职责后,相信朋友可以很清晰的找到对应所需要了解的类。这里大致介绍两个包中的内容,org.gaochun.adapter 和 org.gaochun.widget ,其他包在之前介绍网络框架中大致有提到,看如下两个包中的内容:

            

一个是通用的Adapter和通用的ViewHolder缓存类,一个是自定义的提示框、圆形ImageView、带声音的Toast 。

有时候项目里面有好多好多ListView,记得以前一种傻逼的做法是往 adapter 包中塞各种 OrderAdapter,HistoryAdapter,...... 然后每个 adapter 都是 extends BaseAdapter,如果有一百个Adapter,我去,这他妈是个什么概念。。。。嘿嘿,后来学乖了哟。

关于通用Adapter可参考:https://github.com/JoanZapata/base-adapter-helper


CommonAdapter:

package org.gaochun.adapter;import java.util.List;import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;/*** 通用 Adapter* https://github.com/JoanZapata/base-adapter-helper* @param <T>*/
public abstract class CommonAdapter<T> extends BaseAdapter{protected LayoutInflater mInflater;protected Context mContext;protected List<T> mDatas;protected final int mItemLayoutId;/*** 初始化通用Adapter* @param context   上下文* @param mDatas    需要显示的数据集合* @param itemLayoutId  子布局文件*/public CommonAdapter(Context context, List<T> mDatas, int itemLayoutId){this.mContext = context;this.mInflater = LayoutInflater.from(mContext);this.mDatas = mDatas;this.mItemLayoutId = itemLayoutId;}@Overridepublic int getCount(){return mDatas.size();}@Overridepublic T getItem(int position){return mDatas.get(position);}@Overridepublic long getItemId(int position){return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent){//从ViewHolder中获取控件view,若为空则创建final ViewHolder viewHolder = getViewHolder(position, convertView,parent);Log.i("gao_chun", position+"");convert(viewHolder, getItem(position));return viewHolder.getConvertView();}/*** 抽取出getView中间改变的部分* @param helper    holder缓存对象* @param item      Bean对象*/public abstract void convert(ViewHolder helper, T item);/*** 获得ViewHolder中的view* @param position* @param convertView* @param parent* @return*/private ViewHolder getViewHolder(int position, View convertView,ViewGroup parent){return ViewHolder.get(mContext, convertView, parent, mItemLayoutId,position);}}

ViewHolder:

package org.gaochun.adapter;import android.content.Context;
import android.graphics.Bitmap;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;import com.nostra13.universalimageloader.core.ImageLoader;/*** 通用 ViewHolder 缓存类* @author gao_chun**/
public class ViewHolder{private ImageLoader imageLoader = ImageLoader.getInstance();private final SparseArray<View> mViews;private int mPosition;private View mConvertView;private ViewHolder(Context context, ViewGroup parent, int layoutId,int position){this.mPosition = position;this.mViews = new SparseArray<View>();mConvertView = LayoutInflater.from(context).inflate(layoutId, parent,false);mConvertView.setTag(this);   // setTag}/*** 拿到一个ViewHolder对象** @param context* @param convertView* @param parent* @param layoutId* @param position* @return*/public static ViewHolder get(Context context, View convertView,ViewGroup parent, int layoutId, int position){if (convertView == null){//创建ViewHolder对象 ,并做View缓存return new ViewHolder(context, parent, layoutId, position);}return (ViewHolder)convertView.getTag();}public View getConvertView(){return mConvertView;}/*** 通过控件的Id获取对于的控件,如果没有则加入views** @param viewId* @return*/public <T extends View> T getView(int viewId){View view = mViews.get(viewId);if (view == null){view = mConvertView.findViewById(viewId);mViews.put(viewId, view);}return (T)view;}/*** 为TextView设置字符串** @param viewId* @param text* @return*/public ViewHolder setText(int viewId, String text){TextView view = getView(viewId);view.setText(text);return this;}/*** 为ImageView设置图片*  setImageResource* @param viewId* @param drawableId* @return*/public ViewHolder setImageResource(int viewId, int drawableId){ImageView view = getView(viewId);view.setImageResource(drawableId);return this;}/*** 为ImageView设置图片*  setImageBitmap* @param viewId* @param drawableId* @return*/public ViewHolder setImageBitmap(int viewId, Bitmap bm){ImageView view = getView(viewId);view.setImageBitmap(bm);return this;}/*** 为ImageView设置图片*  setImageByUrl* @param viewId* @param drawableId* @return*//* public ViewHolder setImageByUrl(int viewId, String url){ImageLoader.getInstance(3, Type.LIFO).loadImage(url,(ImageView) getView(viewId));return this;}*/public ViewHolder setImageByUrl(int viewId, String url){imageLoader.displayImage(url,(ImageView)getView(viewId));return this;}public int getPosition(){return mPosition;}}

这里还要给大家推荐一个技巧: ListView中按钮监听器 设置 及 优化,有个需要注意的地方是 setTag 可以记录信息。

下面是实现带声音的Toast控件类源码,大家可以下载源码了解学习:

package org.gaochun.widget;import com.washcar.R;import android.content.Context;
import android.media.MediaPlayer;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;/*** 自定义声音提示 Toast控件* @version 0.1* @created gao_chun*/
public class SoundToast extends Toast{private MediaPlayer mPlayer;private boolean isSound;public SoundToast(Context context){this(context, false);}public SoundToast(Context context, boolean isSound){super(context);this.isSound = isSound;mPlayer = MediaPlayer.create(context, R.raw.newdatatoast);mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener(){@Overridepublic void onCompletion(MediaPlayer mp){mp.release();   //释放资源}});}@Overridepublic void show(){super.show();if (isSound){mPlayer.start();}}/*** 获取控件实例** @param context* @param text  提示消息* @param isSound   是否播放声音* @param duration  时长* @return*/public static SoundToast show(Context context, CharSequence text, boolean isSound, int duration){SoundToast result = new SoundToast(context, isSound);LayoutInflater inflate = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);DisplayMetrics dm = context.getResources().getDisplayMetrics();View v = inflate.inflate(R.layout.layout_toast, null); //加载Toast布局v.setMinimumWidth(dm.widthPixels);  //设置控件最小宽度为手机屏幕宽度TextView tv = (TextView) v.findViewById(R.id.tv_lable);tv.setText(text);result.setView(v);result.setDuration(duration);// 设置 显示多长时间;//result.setGravity(Gravity.CENTER,0,0);return result;}}

注:语音提示播报功能已经实现,在接收到服务器推送的订单后自动播报。由于目前方便测试,在首页点击 订单中 按钮便可看到效果。部分自定义控件这里也不过多的介绍了,感兴趣的童鞋可以下载了研究研究,没准以后在自己项目中就用到了。关于语音播报,在讯飞平台注册了ID,之前简单介绍过一些用法:Android语音播报、后台播报、语音识别 ,大家可以参考下。

关于界面

关于res目录下的界面,想了想,貌似也没有什么好说的了,只需要掌握一些常用的布局技巧,熟练使用Android中的布局属性,基本上简单的界面没有什么太大的问题。由于使用了 dimens 做适配,只需要将使用dp的地方,换成如:android:padding="@dimen/dimen_20_dip" 就可以了,如登录界面:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@color/background" ><LinearLayoutandroid:id="@+id/layout_table"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="@dimen/dimen_30_dip"android:orientation="vertical" ><include layout="@layout/layout_line_horizonal" /><EditTextandroid:id="@+id/edit_username"style="@style/text_16"android:layout_width="match_parent"android:layout_height="@dimen/dimen_75_dip"android:background="@color/white"android:hint="@string/text_hint_username"android:inputType="phone"android:maxLength="11"android:padding="@dimen/dimen_20_dip"android:textColorHint="@color/text_hint_color" /><EditTextandroid:id="@+id/edit_password"style="@style/text_16"android:layout_width="match_parent"android:layout_height="@dimen/dimen_75_dip"android:layout_marginTop="@dimen/row_margin"android:background="@color/white"android:hint="@string/text_hint_password"android:inputType="textPassword"android:padding="@dimen/dimen_20_dip"android:textColorHint="@color/text_hint_color" /><include layout="@layout/layout_line_horizonal" /></LinearLayout><Buttonandroid:id="@+id/button_login"style="@style/text_white_18"android:layout_width="match_parent"android:layout_height="@dimen/dimen_60_dip"android:layout_below="@+id/layout_table"android:layout_marginTop="@dimen/dimen_65_dip"android:background="@drawable/button_selector"android:gravity="center"android:onClick="onClick"android:text="@string/text_login" /></RelativeLayout>

个人中心界面:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@color/background" ><RelativeLayoutandroid:id="@+id/layout_top"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="@color/white" ><RelativeLayoutandroid:id="@+id/layout_table"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="@drawable/person_bg"android:padding="@dimen/dimen_20_dip" ><org.gaochun.widget.RoundImageViewandroid:id="@+id/iv_avatar"android:layout_width="@dimen/dimen_135_dip"android:layout_height="@dimen/dimen_135_dip"android:layout_marginLeft="@dimen/dimen_20_dip"android:layout_marginRight="@dimen/dimen_10_dip"android:scaleType="centerCrop"android:src="@drawable/gao_chun" /><TextViewandroid:id="@+id/tv_user_name"style="@style/text_white_16"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="@dimen/dimen_60_dip"android:layout_marginTop="@dimen/dimen_30_dip"android:layout_toRightOf="@+id/iv_avatar"android:text="gao_chun"android:textStyle="bold" /><TextViewandroid:id="@+id/tv_user_money"style="@style/text_white_16"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_below="@+id/tv_user_name"android:layout_marginLeft="@dimen/dimen_45_dip"android:layout_marginTop="@dimen/dimen_20_dip"android:layout_toRightOf="@+id/iv_avatar"android:text="余额:12345"android:textStyle="bold" /></RelativeLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_below="@+id/layout_table"android:orientation="horizontal"android:padding="@dimen/dimen_20_dip" ><TextViewstyle="@style/text_16"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="@dimen/dimen_25_dip"android:layout_weight="1"android:text="优评:2" /><Viewandroid:layout_width="1px"android:layout_height="match_parent"android:layout_marginRight="@dimen/dimen_40_dip"android:background="@color/line_gray" /><TextViewstyle="@style/text_16"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_weight="1"android:text="中评:4" /><Viewandroid:layout_width="1px"android:layout_height="match_parent"android:layout_marginRight="@dimen/dimen_40_dip"android:background="@color/line_gray" /><TextViewstyle="@style/text_16"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_weight="1"android:text="差评:0" /></LinearLayout></RelativeLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_below="@+id/layout_top"android:layout_marginTop="@dimen/dimen_30_dip"android:orientation="vertical" ><Viewandroid:layout_width="match_parent"android:layout_height="1px"android:background="@color/line_gray" /><TextViewandroid:id="@+id/tv_my_order"style="@style/text_black_16"android:layout_width="match_parent"android:layout_height="@dimen/dimen_75_dip"android:background="@drawable/row_selector"android:clickable="true"android:drawableLeft="@drawable/person_order"android:drawablePadding="@dimen/dimen_40_dip"android:gravity="center_vertical"android:onClick="onClick"android:padding="@dimen/dimen_25_dip"android:text="@string/text_my_order" /><TextViewandroid:id="@+id/tv_my_vip"style="@style/text_black_16"android:layout_width="match_parent"android:layout_height="@dimen/dimen_75_dip"android:layout_marginTop="@dimen/row_margin"android:background="@drawable/row_selector"android:clickable="true"android:drawableLeft="@drawable/person_vip"android:drawablePadding="@dimen/dimen_40_dip"android:gravity="center_vertical"android:onClick="onClick"android:padding="@dimen/dimen_25_dip"android:text="@string/text_my_vip" /><TextViewandroid:id="@+id/tv_my_notify"style="@style/text_black_16"android:layout_width="match_parent"android:layout_height="@dimen/dimen_75_dip"android:layout_marginTop="@dimen/row_margin"android:background="@drawable/row_selector"android:clickable="true"android:drawableLeft="@drawable/person_inform"android:drawablePadding="@dimen/dimen_40_dip"android:gravity="center_vertical"android:onClick="onClick"android:padding="@dimen/dimen_25_dip"android:text="@string/text_my_information" /><TextViewandroid:id="@+id/tv_my_more"style="@style/text_black_16"android:layout_width="match_parent"android:layout_height="@dimen/dimen_75_dip"android:layout_marginTop="@dimen/row_margin"android:background="@drawable/row_selector"android:clickable="true"android:drawableLeft="@drawable/person_more"android:drawablePadding="@dimen/dimen_40_dip"android:gravity="center_vertical"android:onClick="onClick"android:padding="@dimen/dimen_25_dip"android:text="@string/text_more" /><include layout="@layout/layout_line_horizonal" /></LinearLayout><Buttonandroid:id="@+id/button_submit"style="@style/text_white_18"android:layout_width="match_parent"android:layout_height="@dimen/dimen_65_dip"android:layout_alignParentBottom="true"android:layout_marginBottom="@dimen/dimen_40_dip"android:background="@drawable/button_selector"android:gravity="center"android:onClick="onClick"android:text="@string/text_exit" /></RelativeLayout>

关于其他技术点,日后总结了看有没有必要给大家再介绍下,先就到这里吧!

源码下载:http://download.csdn.net/download/gao_chun/8861137

【注:转载注明gao_chun的BLOG http://blog.csdn.net/gao_chun/article/details/46711649】

上门洗车APP --- Android客户端开发 之 项目结构介绍相关推荐

  1. 上门洗车APP --- Android客户端开发 之 网络框架封装介绍(一)

    上门洗车APP --- Android客户端开发 之 网络框架封装介绍(一) 上篇文章中给大家简单介绍了一些业务,上门洗车APP --- Android客户端开发 前言及业务简介,本篇文章给大家介绍下 ...

  2. 原生Android开发基础项目结构介绍

    原生Android开发基础项目结构介绍 1.软件整体结构 2.具体的页面书写 3.实例分析 4.后续     下面先来总结一下软件的基本目录结构,这一般是开发的关键,只有明白了软件的目录结构,才能更加 ...

  3. 腾讯微博Android客户端开发 - OAuth1.0认证介绍

    2019独角兽企业重金招聘Python工程师标准>>> http://wiki.open.t.qq.com/index.php/OAuth%E6%8E%88%E6%9D%83%E8% ...

  4. AngularJS+Ionic开发-2.项目结构介绍

    使用上篇博客<开发环境搭建>中的命令创建完成IonicHelloWorld项目,在VSCode中的左侧,显示该项目的结构信息,如下图所示: 1 .sourcesmaps文件夹 调试状态的j ...

  5. 行代码入门python_新浪微博Android客户端开发视频教程(36讲)

    教程名称:新浪微博Android客户端开发视频教程(36讲) 课程目录: [IT教程网]新浪微博Android客户端介绍 [IT教程网]新浪微博Android客户端相关资料 [IT教程网]新浪微博An ...

  6. 上门洗车小程序软件开发所需要的功能有哪些呢?

    相信很多企业及投资者都想开发一款属于自己的小程序系统.那么一款专业好用的上门洗车小程序软件开发所需要的功能有哪些呢?        1. 用户注册与登录.        用户可以通过手机号码或微信账号 ...

  7. android 腾讯微博授权,5腾讯微博Android客户端开发获取请求用户授权Request Token.pdf...

    腾讯微博Android客户端开发 博客:/coolszy Android Android 腾讯微博AAnnddrrooiidd客户端开发 RequestToken RequestToken --获取请 ...

  8. vue-cli构建SPA项目结构介绍spa完成路由开发及嵌套路由

    目录 一.vue-cli构建SPA项目结构介绍 二.spa完成路由开发 三. 嵌套路由 一.vue-cli构建SPA项目结构介绍 前提:搭建好NodeJS环境    node -v    npm -v ...

  9. .NET Core实战项目之CMS 第十三章 开发篇-在MVC项目结构介绍及应用第三方UI

    作为后端开发的我来说,前端表示真心玩不转,你如果让我微调一个位置的样式的话还行,但是让我写一个很漂亮的后台的话,真心做不到,所以我一般会选择套用一些开源UI模板来进行系统UI的设计.那如何套用呢?今天 ...

  10. 六十一、分析Springboot中的项目结构介绍

    @Author:Runsen 来源:尚硅谷 下面建议读者学习尚硅谷的B站的SpringBoot视频,我是学雷丰阳视频入门的. 具体链接如下:B站尚硅谷SpringBoot教程 文章目录 spring项 ...

最新文章

  1. maven 一个模块生成多个jar包
  2. salesforce学习框架图
  3. matlab p-tite分割图像,P'tite fourmi
  4. Winform开发几个常用的开发经验及知识积累(一)
  5. 机器学习——线性回归数学推导
  6. fast_recovery_area无剩余空间(ORA-19815)
  7. 【大会】嵌入式玩直播,IoT做前处理
  8. shocked的歌曲 类似shell_Shell Shocked歌词
  9. Interval(区间类问题)
  10. ICE Tester method viewer 的安装和使用,和客制化代码配合使用
  11. sift算法c语言实现
  12. matlab转换器dcdc,用 Simulink 设计 DC/DC 转换器
  13. 正确的座机号码格式_简历里的手机号及座机号的标准写法是什么?正确书写才更可能求职成功!...
  14. hive中导入csv,把csv导入到hive表中步骤
  15. 软件开发工具【五】 之 软件开发工具的使用与开发
  16. 一文搞懂底层mysql 索引那些事
  17. 浏览器被23545等网站劫持,以Chrome为例亲测有效的两个解除劫持的方法
  18. Fiddler的下载与基本使用方法
  19. buuoj Pwn writeup 246-250
  20. linux下TSL如何升级,glibc升级

热门文章

  1. 首席新媒体运营商学院黎想:裂变活动要避免40个坑!
  2. 计算机无理数转根号,[转载]从根号二是无理数到孤独的根号三
  3. implicit declaration of function —— 函数隐式声明 警告
  4. EMC辐射骚扰整改案例分析
  5. Linux内核设计与实现 总结笔记(第六章)内核数据结构
  6. 技术小卡之Redis 管道技术
  7. Android性能优化——启动优化简述
  8. opencv--normalize函数详解
  9. CSDN:2020 年度 CSDN 博客之星评选——28 号【沉默王二】,感谢你投上的宝贵一票,感谢!
  10. 怎么样向云服务器上传文件_如何上传文件到阿里云服务器?