Android开发之代码优化

从最早第一天上C语言课的时候,我老师就跟我们讲过,别啥玩意都写在main函数里面,把里面的东西分离出来封装一下,然后在main函数中调用。当时写的是算法题,其实只要能得出正确答案,并不用太过于在意代码的机构。可是如果写Android项目的话,动辄上万行代码,全写在四大组件里,其实没有任何问题,项目一样能跑的起来,不过那样的代码可维护性,拓展性,可读性都会非常烂。以前写过一个制作表情包的App,先开始项目的主要代码全部压在了Activity里面,也没怎么在意,后来觉得这项目写的太烂,又把代码重构了一遍,虽然项目的功能完全没有变,可是代码的逻辑和结构变得更加清晰,也更易于维护拓展了。因为项目的代码量比较大,而这篇博文主要想讲解的是代码优化,所以写了个简化版的作为讲解,去掉了原来项目里大部分的功能,只留些许的功能讲解其中数据和视图的分离。

这里写图片描述

左边的ListView单机可以添加图片进表情包,右边的ListView是可以选取某个图片进行操作,长按则删除,中间的是个控制面板,可以通过触碰对图片进行位置移动//原项目没这么丑,这是简化版的,各位看官担待。

先贴原先的代码 ,也就是没进行过优化前所有代码都积压在Activity的代码

item_layout.xml

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="70dp">
    <ImageView
        android:id="@+id/type_image"
        android:layout_centerVertical="true"
        android:layout_width="50dp"
        android:layout_height="50dp" />
</RelativeLayout>

activity_main.xml

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.cjm.simplefight.MainActivity">
    <ImageView
        android:id="@+id/fight_img"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:orientation="horizontal">
        <ListView
            android:id="@+id/ori_list"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
        <com.example.cjm.simplefight.MoveView
            android:id="@+id/move_view"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
        <ListView
            android:id="@+id/img_list"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
    </LinearLayout>
</LinearLayout>
public class ViewItem {

    private Bitmap bitmap;
    private int x;
    private int y;

    public Bitmap getBitmap() {
        return bitmap;
    }

    public void setBitmap(Bitmap bitmap) {
        this.bitmap = bitmap;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

}
public class MoveView extends View {

    /*
    * 该控件为控制台中操控元素上下左右移动的控件
    * 提供了一个接口
    * 回调了手指在该控件的移动情况
    * 这样就可以使元素进行相应的移动
    * */

    private int color=getResources().getColor(R.color.mycolor);
    private float startX;
    private float startY;
    public interface MoveViewListener{
        void move(float staX,float staY,float stoX,float stoY);
    }
    private MoveViewListener moveViewListener;

    public void setMoveViewListener(MoveViewListener moveViewListener) {
        this.moveViewListener = moveViewListener;
    }

    public MoveView(Context context) {
        this(context, null);
    }

    public MoveView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MoveView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                startX=event.getX();
                startY=event.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                float stopX=event.getX();
                float stopY=event.getY();
                moveViewListener.move(startX,startY,stopX,stopY);
                startX=stopX;
                startY=stopY;
                break;
            case MotionEvent.ACTION_UP:
                break;
        }
        return true;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(color);
    }

}
public class ImgAdapter extends BaseAdapter{

    private List<ViewItem> itemList;
    private LayoutInflater inflater;

    public ImgAdapter(Context context,List<ViewItem> itemList){
        this.itemList=itemList;
        inflater=LayoutInflater.from(context);
    }

    @Override
    public int getCount() {
        return itemList.size();
    }

    @Override
    public Object getItem(int position) {
        return itemList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        AdapterHolder holder=null;
        ViewItem viewItem=itemList.get(position);
        if(convertView==null){
            holder=new AdapterHolder();
            //当元素类别为图片时,加载图片的布局
            convertView=inflater.inflate(R.layout.item_layout,parent,false);
            holder.type_image=(ImageView)convertView.findViewById(R.id.type_image);
            convertView.setTag(holder);
        }else{
            holder=(AdapterHolder)convertView.getTag();
        }
        holder.type_image.setImageBitmap(viewItem.getBitmap());

        return convertView;
    }

    private final class AdapterHolder{
        private ImageView type_image;
    }

}

public class MainActivity extends Activity {

    private int poi=-1;
    private Bitmap picture;
    private ImageView imageView;
    private ListView ori_list;
    private ListView img_list;
    private List<ViewItem> oriItems;
    private List<ViewItem> imgItems;
    private ImgAdapter oriAdapter;
    private ImgAdapter imgAdapter;
    private MoveView moveView;
    private int res[]={R.drawable.a10,R.drawable.a11,R.drawable.a12,R.drawable.a13,R.drawable.a14,R.drawable.a15};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        InitData();
        InitView();
        InitListener();
    }

    private void InitData(){
        oriItems=new ArrayList<ViewItem>();
        imgItems=new ArrayList<ViewItem>();
        for(int i:res){
            ViewItem item=new ViewItem();
            item.setBitmap(BitmapFactory.decodeResource(getResources(),i));
            oriItems.add(item);
        }
    }

    private void InitView(){
        oriAdapter=new ImgAdapter(this,oriItems);
        imgAdapter=new ImgAdapter(this,imgItems);
        imageView=(ImageView)findViewById(R.id.fight_img);
        ori_list=(ListView)findViewById(R.id.ori_list);
        img_list=(ListView)findViewById(R.id.img_list);
        moveView=(MoveView)findViewById(R.id.move_view);
        ori_list.setAdapter(oriAdapter);
        img_list.setAdapter(imgAdapter);
    }

    private void InitListener(){
        ori_list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                ViewItem item=oriItems.get(position);
                ViewItem newItem=new ViewItem();
                newItem.setX(30);
                newItem.setY(30);
                newItem.setBitmap(item.getBitmap());
                imgItems.add(item);
                imgAdapter.notifyDataSetChanged();
                draw();
            }
        });
        img_list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                poi=position;
                draw();
            }
        });
        moveView.setMoveViewListener(new MoveView.MoveViewListener() {
            @Override
            public void move(float staX, float staY, float stoX, float stoY) {
                Amove(staX,staY,stoX,stoY);
                draw();
            }
        });
    }

    private void draw(){
        picture = Bitmap.createBitmap(imageView.getWidth(), imageView.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas=new Canvas(picture);
        canvas.drawColor(Color.WHITE);
        for(ViewItem item:imgItems) {
            canvas.drawBitmap(item.getBitmap(), item.getX(), item.getY(), null);
        }
        if(poi!=-1){
            ViewItem item=imgItems.get(poi);
            Paint pc = new Paint();
            pc.setStrokeWidth(5);
            pc.setStyle(Paint.Style.STROKE);
            canvas.drawRect(item.getX(), item.getY(), item.getX() + item.getBitmap().getWidth(),
                    item.getY() + item.getBitmap().getHeight(), pc);
        }
        imageView.setImageBitmap(picture);
    }

    private void Amove(float staX, float staY, float stoX, float stoY){
        int moveX = (int) (stoX - staX);
        int moveY = (int) (stoY - staY);
        ViewItem item = imgItems.get(poi);
        item.setX(item.getX() + moveX);
        item.setY(item.getY() + moveY);
    }

}

项目代码就这么多,主要的逻辑都在Activity里面了,非常不好维护,现在从MainActivity方法中把数据抽离出来封装成ViewController类,去控制数据,然后提供相应的public函数供MainActivity去调用,一方面使数据相对独立自制,MainActivity的代码也会变得简洁很多,只需要去生成相应的Data,View,Listener函数就可以了
下面是把MainActivity抽离出来的两个类

public class ViewController {

    private List<ViewItem> itemList;
    private Bitmap picture=null;

    public ViewController(){
        itemList=new ArrayList<ViewItem>();
    }

    public List<ViewItem> getList(){
        return itemList;
    }

    public void addItem(ViewItem item){
        itemList.add(item);
    }

    public void draw(ImageView imageView,int poi){
        picture = Bitmap.createBitmap(imageView.getWidth(), imageView.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas=new Canvas(picture);
        canvas.drawColor(Color.WHITE);
        for(ViewItem item:itemList) {
            canvas.drawBitmap(item.getBitmap(), item.getX(), item.getY(), null);
        }
        if(poi!=-1){
            ViewItem item=itemList.get(poi);
            Paint pc = new Paint();
            pc.setStrokeWidth(5);
            pc.setStyle(Paint.Style.STROKE);
            canvas.drawRect(item.getX(), item.getY(), item.getX() + item.getBitmap().getWidth(),
                    item.getY() + item.getBitmap().getHeight(), pc);
        }
        imageView.setImageBitmap(picture);
    }

    public void move(int poi,float staX, float staY, float stoX, float stoY){
        int moveX = (int) (stoX - staX);
        int moveY = (int) (stoY - staY);
        ViewItem item = itemList.get(poi);
        item.setX(item.getX() + moveX);
        item.setY(item.getY() + moveY);
    }

}
public class MainActivity extends Activity {

    private int poi=-1;
    private ImageView imageView;
    private ListView ori_list;
    private ListView img_list;
    private List<ViewItem> oriItems;
    private ImgAdapter oriAdapter;
    private ImgAdapter imgAdapter;
    private ViewController viewController;
    private MoveView moveView;
    private int res[]={R.drawable.a10,R.drawable.a11,R.drawable.a12,R.drawable.a13,R.drawable.a14,R.drawable.a15};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        InitData();
        InitView();
        InitListener();
    }

    private void InitData(){
        viewController=new ViewController();
        oriItems=new ArrayList<ViewItem>();
        for(int i:res){
            ViewItem item=new ViewItem();
            item.setBitmap(BitmapFactory.decodeResource(getResources(),i));
            oriItems.add(item);
        }
    }

    private void InitView(){
        oriAdapter=new ImgAdapter(this,oriItems);
        imgAdapter=new ImgAdapter(this,viewController.getList());
        imageView=(ImageView)findViewById(R.id.fight_img);
        ori_list=(ListView)findViewById(R.id.ori_list);
        img_list=(ListView)findViewById(R.id.img_list);
        moveView=(MoveView)findViewById(R.id.move_view);
        ori_list.setAdapter(oriAdapter);
        img_list.setAdapter(imgAdapter);
    }

    private void InitListener(){
        ori_list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                ViewItem item=oriItems.get(position);
                ViewItem newItem=new ViewItem();
                newItem.setX(30);
                newItem.setY(30);
                newItem.setBitmap(item.getBitmap());
                viewController.addItem(item);
                imgAdapter.notifyDataSetChanged();
                viewController.draw(imageView,poi);
            }
        });
        img_list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                poi=position;
                viewController.draw(imageView,poi);
            }
        });
        moveView.setMoveViewListener(new MoveView.MoveViewListener() {
            @Override
            public void move(float staX, float staY, float stoX, float stoY) {
                viewController.move(poi,staX,staY,stoX,stoY);
                viewController.draw(imageView,poi);
            }
        });
    }

}

或许是因为这个项目其实也很小,看不出这种写法的优越之处,当一个Activity的代码量庞大的时候,会明显感觉到一个整合Activity中所用到的数据的类的好处。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值