android设计模式 App的设计架构

自古深情留不住 总是套路得人心

为啥说上面这句话呢,因为所谓的设计模式其实就是套路,套路呢还比较受大家喜欢。

为啥使用设计模式呢,无非高内聚低耦合。

 

 

Android中的MVC

 

Android中界面部分也采用了当前比较流行的MVC框架,在Android中:

  • 视图层(View)

一般采用XML文件进行界面的描述,这些XML可以理解为AndroidApp的View。使用的时候可以非常方便的引入。同时便于后期界面的修改。逻辑中与界面对应的id不变化则代码不用修改,大大增强了代码的可维护性。

  • 控制层(Controller)

Android的控制层的重任通常落在了众多的Activity的肩上。这句话也就暗含了不要在Activity中写代码,要通过Activity交割Model业务逻辑层处理,这样做的另外一个原因是Android中的Actiivity的响应时间是5s,如果耗时的操作放在这里,程序就很容易被回收掉。

  • 模型层(Model)

我们针对业务模型,建立的数据结构和相关的类,就可以理解为AndroidApp的Model,Model是与View无关,而与业务相关的(感谢@Xander的讲解)。对数据库的操作、对网络等的操作都应该在Model里面处理,当然对业务计算等操作也是必须放在的该层的。就是应用程序中二进制的数据。

 

 

 

MVP从更早的MVC框架演变过来,与MVC有一定的相似性:Controller/Presenter负责逻辑的处理,Model提供数据,View负责显示。

MVP框架由3部分组成:View负责显示,Presenter负责逻辑处理,Model提供数据。在MVP模式里通常包含3个要素(加上View interface是4个):

  • View:负责绘制UI元素、与用户进行交互(在Android中体现为Activity)

  • Model:负责存储、检索、操纵数据(有时也实现一个Model interface用来降低耦合)

  • Presenter:作为View与Model交互的中间纽带,处理与用户交互的负责逻辑。

  • *View interface:需要View实现的接口,View通过View interface与Presenter进行交互,降低耦合,方便进行单元测试

 

 

 

 

两种模式的主要区别:

  • (最主要区别)View与Model并不直接交互,而是通过与Presenter交互来与Model间接交互。而在MVC中View可以与Model直接交互

  • 通常View与Presenter是一对一的,但复杂的View可能绑定多个Presenter来处理逻辑。而Controller是基于行为的,并且可以被多个View共享,Controller可以负责决定显示哪个View

  • Presenter与View的交互是通过接口来进行的,更有利于添加单元测试。

 

 

 

 

 

设计模式文章https://www.cnblogs.com/cr330326/p/5627658.html

 

 

1,工厂模式

工厂模式适合:凡是出现了大量的产品需要创建,并且具有共同的接口时,可以通过工厂方法模式进行创建。

public interface Sender {  

    public void Send();  

}  

其次,创建实现类:

public class MailSender implements Sender {  

    @Override  

    public void Send() {  

        System.out.println("this is mailsender!");  

    }  

}  

public class SmsSender implements Sender {  

    @Override  

    public void Send() {  

        System.out.println("this is sms sender!");  

    }  

}  

public class SendFactory {  

    public static Sender produceMail(){  

        return new MailSender();  

    }  

    public static Sender produceSms(){  

        return new SmsSender();  

    }  

}  

 

public class FactoryTest {  

    public static void main(String[] args) {      

        Sender sender = SendFactory.produceMail();  

        sender.Send();  

    }  

}  

 

2,单例模式

单例对象(Singleton)是一种常用的设计模式。在Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在。这样的模式有几个好处:

1、某些类创建比较频繁,对于一些大型的对象,这是一笔很大的系统开销。

2、省去了new操作符,降低了系统内存的使用频率,减轻GC压力。

3、有些类如交易所的核心交易引擎,控制着交易流程,如果该类可以创建多个的话,系统完全乱了。(比如一个军队出现了多个司令员同时指挥,肯定会乱成一团),所以只有使用单例模式,才能保证核心交易服务器独立控制整个流程。

饿汉式-程序加载class文件的时候对象就会被创建,线程不安全

 private static Singleton instance = new Singleton();  

public static Singleton getInstance() {  

    return instance;    }

懒汉式-使用的时候才会被创建,线程安全双重锁

public static Singleton getInstance() {  

        if (instance == null) {  

            synchronized (instance) {  

                if (instance == null) {  

                    instance = new Singleton();                  }              }          }  

        return instance;      }  

3,Bulider模式

public class PersonThree {

    //固定不变的对象,一般变量需要声明为 final

    private final String mName;    //必选,final 类型需要在 构造器中初始化,不允许不初始化它的构造器存在

    private String mLocation;      //可选

    private String mJob;            //可选

    private String mHabit;          //可选

    /**

    * 构造方法的参数是它的 静态内部类,使用静态内部类的变量一一赋值

    * @param builder

    */

    public PersonThree(Builder builder) {

        this.mName = builder.mName;

        this.mLocation = builder.mLocation;

        this.mJob = builder.mJob;

        this.mHabit = builder.mHabit;

    }

    /**

    * PersonTree 的静态内部类,成员变量和 PersonTree 的一致

    */

    public static class Builder{

        private final String mName;    //必选,final 类型需要在 构造器中初始化,不允许不初始化它的构造器存在

        private String mLocation;      //可选

        private String mJob;            //可选

        private String mHabit;          //可选

        /**

        * 含必选参数的构造方法

        * @param name

        */

        public Builder(String name) {

            mName = name;

        }

        public Builder setLocation(String location) {

            mLocation = location;

            return this;

        }

        public Builder setJob(String job) {

            mJob = job;

            return this;

        }

        public Builder setHabit(String habit) {

            mHabit = habit;

            return this;

        }

        /**

        * 最终构建方法,返回一个 PersonTree 对象,参数是当前 Builder 对象

        * @return

        */

        public PersonThree build(){

            return new PersonThree(this);

        }

    }

}

调用:

    new PersonThree.Builder("shixinzhang")

            .setLocation("Shanghai")

            .setJob("Android Develop")

            .setHabit("LOL")

            .build();

 

4,适配器模式

即列表传入不同的数据显示不同的列表展示

5,代理模式

代理模式就是多一个代理类出来,替原对象进行一些操作,比如处理按钮的多次点击

public class ClickProxyimplements View.OnClickListener {

private View.OnClickListenerorigin;

    private long last_click =0;

    private long time_ms =1000; //ms

    private IAgainmIAgain;

    public ClickProxy(View.OnClickListener origin, long time_ms, IAgain again) {

this.origin = origin;

        this.mIAgain = again;

        this.time_ms = time_ms;

    }

public ClickProxy(View.OnClickListener origin) {

this.origin = origin;

    }

@Override

    public void onClick(View v) {

if (System.currentTimeMillis() -last_click >=time_ms) {

origin.onClick(v);

            last_click = System.currentTimeMillis();

        }else {//重复点击

            if (mIAgain !=null)mIAgain.onAgain();

        }

}

public interface IAgain {

void onAgain();//重复点击

    }

}

btn_notification.setOnClickListener(new ClickProxy(new View.OnClickListener() {

@Override

    public void onClick(View v) {

    }}));

 

6,观察者模式

 

按钮点击

刚学安卓的时候 ,按钮点击是必不可少的 ,我们先来回顾一下其中的套路

相信大家对此都不陌生了

如果你连这个都没有写的很熟练 ,那此篇文章可能不适合你了

//寻找控件 Button bt = (Button) findViewById(R.id.bt);//实例化一个监听 View.OnClickListener clickListener =newView.OnClickListener() {@OverridepublicvoidonClick(View view){//点击事件 //your code }    };//为按钮控件设置点击监听 bt.setOnClickListener(clickListener );

当然这样做的目的是为了更好的理解观察者模式

在这里 我们称 Button 为 被观察者 ( Observable )

这个单词还是很重要的 RxJava 里面还会用到

当然可想而知 OnClickListener 就是观察者 ( Observer ) 了

被观察者可以有多个观察者 这个叫做订阅机制 (Subscribe)

当被观察者的状态发生改变 观察者就做出相应的动作

这个就叫做 观察者模式

 

 

Android设计模式系列-组合模式

  将对象View和ViewGroup组合成树形结构以表示"部分-整体"的层次结构(View可以做为ViewGroup的一部分,ViewGroup也可以被用户当做一  个view)。组合模式使得用户对单个对象View和组合对象ViewGroup的使用具有一致性。

 

 

Android设计模式系列-单例模式

保证一个类仅有一个实例,并提供一个访问它的全局访问点,synchronized关键字,在多线程的环境下,单例模式为了保证自己实例数量的唯一,必然会做并发控制,多线程下的线程安全。

 

(1).创建型模式。
(2).对唯一实例的受控访问。
(3).避免全局变量污染命名空间。
(4).允许对操作和表示的精化。
(5).比类操作更灵活。

 

 public class Singleton { 

  private static Singleton instance = null;

        private Singleton(){}

  public static synchronized Singleton getInstance() {

       //也可以这样写:synchronized public static Singleton getInstance() {

      if (instance == null){

       instance = new Singleton();

           }

           return instance; 

     } 

 

避免单例引起的内存泄漏

 

private static DisplayUtils instance = null;
private Context mContext;

private DisplayUtils(Context context) {        //这里变化了,把当前Context指向个应用程序的Context
    this.mContext = context.getApplicationContext();
}

public static DisplayUtils getInstance(Context context) {
    if (instance == null) {
        synchronized (DisplayUtils.class) {
            if (instance == null) {
                instance = new DisplayUtils(context);
            }
        }
    }
    return instance;
}

弱引用的使用

private WeakReference<Context> weakContext;

private DisplayUtils(Context context) { //这里变化了,把当前Context指向个应用程序的Context
weakContext = new WeakReference<Context>(context);
}

public static DisplayUtils getInstance(Context context) {
if (instance == null) {
synchronized (DisplayUtils.class) {
if (instance == null) {
instance = new DisplayUtils(context);
}
}
}
return instance;
}



public int dip2px(float dpValue) {
final float scale = weakContext.get().getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}

 

 

 

Android设计模式系列--工厂方法模式

 

public interface Factory{ 

  public Product create(); 

我们再来定义一个产品接口

  1. public interface Product{} 

一下是实现了产品接口的产品类

  1. public class Washer implements Product{ 
  2.    public Washer(){ 
  3.        System.out.println("洗衣机被制造了"); 
  4.    } 
  5.  
  6. public class Icebox implements Product{ 
  7.    public Icebox(){ 
  8.        System.out.println("冰箱被制造了"); 
  9.    } 
  10.  
  11. public class AirCondition implements Product{ 
  12.    public Icebox(){ 
  13.        System.out.println("空调被制造了"); 
  14.    } 

接下来,就是工厂方法的核心部分,也就是具体创建产品对象的具体工厂类,

  1. //创建洗衣机的工厂 
  2. public class CreateWasher implements Factory{ 
  3.     public Product create(){ 
  4.           return new Washer(); 
  5.     } 
  6.  
  7. //创建冰箱的工厂 
  8. public class CreateIcebox implements Factory{ 
  9.     public Product create(){ 
  10.           return new Icebox(); 
  11.     } 
  12.  
  13. //创建空调的工厂 
  14. public class CreateAirCondition implements Factory{ 
  15.     public Product create(){ 
  16.           return new AirCondition(); 
  17.     } 

Android设计模式系列-适配器模式

适配器模式,把一个类的接口变换成客户端所期待的另一种接口,从而使原本不匹配而无法在一起工作的两个,类能够在一起工作。
适配器模式分为类适配器模式和对象适配器模式。

 

Android设计模式系列--观察者模式

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

观察者模式里面目标类维护了所有观察者的引用,而回调里面只是维护了一个引用

比如说广播--广播接受者,就是观察者模式,发起广播,所有注册的广播接受者都会收到。

  button点击,广播接受者

 

  

 

Android设计模式系列--Builder模式

 

 

 

 

 

  在Android中经常要使用AlertDialog来显示一些简单的窗口,通常的写法类似下面的代码 : 

 

[java] view plain copy

  1. AlertDialog dialog = new AlertDialog.Builder(MainActivity.this).setTitle("提示")  
  2.         .setMessage("确定退出?").create();  
  3. dialog.show();  

可以看到dialog是通过Builder创建的,那么Builder是如何同AlertDialog协同工作的呢?其实AlertDialog的创建就是使用Builder模式,废话不多说,直接上代码吧。

 

 

 

 

 

[java] view plain copy

  1. package com.umeng.dp.builder;  
  2.   
  3. /** 
  4.  * @Copyright: Umeng.com, Ltd. Copyright 2011-2015, All rights reserved 
  5.  * @Title: UmengDialog.java 
  6.  * @Package com.umeng.dp.builder 
  7.  * @Description: Builder模式 
  8.  * @author Honghui He 
  9.  * @version V1.0 
  10.  */  
  11.   
  12. public class UmengDialog {  
  13.   
  14.     private String mTitle = "";  
  15.     private String mMessage = "";  
  16.     private int mIcon = -1;  
  17.   
  18.     /** 
  19.      * @Title: UmengDialog 
  20.      * @Description: UmengDialog Constructor 
  21.      * @param builder 将dialog参数传递给builder,够将好的builder传递给Dialog 
  22.      */  
  23.     private UmengDialog(Builder builder) {  
  24.         mTitle = builder.getTitle();  
  25.         mMessage = builder.getMessage();  
  26.         mIcon = builder.getIcon();  
  27.     }  
  28.   
  29.     /** 
  30.      * @Title: show 
  31.      * @Description: show dialog 
  32.      * @throws 
  33.      */  
  34.     public void show() {  
  35.         System.out.println("显示窗口 : " + this);  
  36.     }  
  37.   
  38.     /** 
  39.      * (非 Javadoc) 
  40.      *  
  41.      * @Title: toString 
  42.      * @Description: 
  43.      * @return 
  44.      * @see java.lang.Object#toString() 
  45.      */  
  46.     @Override  
  47.     public String toString() {  
  48.         return "UmengDialog [mTitle=" + mTitle + ", mMessage=" + mMessage + ", mIcon=" + mIcon  
  49.                 + "]";  
  50.     }  
  51.   
  52.     /** 
  53.      * @ClassName: Builder 
  54.      * @Description: Builder模式, 用于构建复杂的对象 
  55.      * @author Honghui He 
  56.      */  
  57.     public static class Builder {  
  58.         private String mDlgTitle = "";  
  59.         private String mDlgMessage = "";  
  60.         private int mDlgIcon = -1;  
  61.   
  62.         /** 
  63.          * @Title: Builder 
  64.          * @Description: Builder Constructor 
  65.          */  
  66.         public Builder() {  
  67.         }  
  68.   
  69.         /** 
  70.          * 获取 mDlgTitle 
  71.          *  
  72.          * @return 返回 mDlgTitle 
  73.          */  
  74.         public String getTitle() {  
  75.             return mDlgTitle;  
  76.         }  
  77.   
  78.         /** 
  79.          * 设置 mDlgTitle 
  80.          *  
  81.          * @param 对mDlgTitle进行赋值 
  82.          */  
  83.         public Builder setTitle(String title) {  
  84.             this.mDlgTitle = title;  
  85.             return this;  
  86.         }  
  87.   
  88.         /** 
  89.          * 获取 mDlgMessage 
  90.          *  
  91.          * @return 返回 mDlgMessage 
  92.          */  
  93.         public String getMessage() {  
  94.             return mDlgMessage;  
  95.         }  
  96.   
  97.         /** 
  98.          * 设置 mDlgMessage 
  99.          *  
  100.          * @param 对mDlgMessage进行赋值 
  101.          */  
  102.         public Builder setMessage(String msg) {  
  103.             this.mDlgMessage = msg;  
  104.             return this;  
  105.         }  
  106.   
  107.         /** 
  108.          * 获取 mDlgIcon 
  109.          *  
  110.          * @return 返回 mDlgIcon 
  111.          */  
  112.         public int getIcon() {  
  113.             return mDlgIcon;  
  114.         }  
  115.   
  116.         /** 
  117.          * 设置 mDlgIcon 
  118.          *  
  119.          * @param 对mDlgIcon进行赋值 
  120.          */  
  121.         public Builder setIcon(int resId) {  
  122.             this.mDlgIcon = resId;  
  123.             return this;  
  124.         }  
  125.   
  126.         /** 
  127.          * @Title: create 
  128.          * @Description: 创建窗口 
  129.          * @throws 
  130.          */  
  131.         public UmengDialog create() {  
  132.             return new UmengDialog(this);  
  133.         }  
  134.     }  
  135.   
  136. }  
  137.  

 

 

 

public class PersonThree {
    //固定不变的对象,一般变量需要声明为 final
    private final String mName;     //必选,final 类型需要在 构造器中初始化,不允许不初始化它的构造器存在
    private String mLocation;       //可选
    private String mJob;            //可选
    private String mHabit;          //可选

    /**
     * 构造方法的参数是它的 静态内部类,使用静态内部类的变量一一赋值
     * @param builder
     */
    public PersonThree(Builder builder) {
        this.mName = builder.mName;
        this.mLocation = builder.mLocation;
        this.mJob = builder.mJob;
        this.mHabit = builder.mHabit;
    }

    /**
     * PersonTree 的静态内部类,成员变量和 PersonTree 的一致
     */
    public static class Builder{
        private final String mName;     //必选,final 类型需要在 构造器中初始化,不允许不初始化它的构造器存在
        private String mLocation;       //可选
        private String mJob;            //可选
        private String mHabit;          //可选

        /**
         * 含必选参数的构造方法
         * @param name
         */
        public Builder(String name) {
            mName = name;
        }

        public Builder setLocation(String location) {
            mLocation = location;
            return this;
        }

        public Builder setJob(String job) {
            mJob = job;
            return this;
        }

        public Builder setHabit(String habit) {
            mHabit = habit;
            return this;
        }

        /**
         * 最终构建方法,返回一个 PersonTree 对象,参数是当前 Builder 对象
         * @return
         */
        public PersonThree build(){
            return new PersonThree(this);
        }
    }
}

调用:

    new PersonThree.Builder("shixinzhang")
            .setLocation("Shanghai")
            .setJob("Android Develop")
            .setHabit("LOL")
            .build();

 

Android设计模式系列--生产者消费者模式

/**
 * 生产者消费者模式:使用Object.wait() / notify()方法实现
 */
public class ProducerConsumer {
    private static final int CAPACITY = 5;

    public static void main(String args[]){
        Queue<Integer> queue = new LinkedList<Integer>();

        Thread producer1 = new Producer("P-1", queue, CAPACITY);
        Thread producer2 = new Producer("P-2", queue, CAPACITY);
        Thread consumer1 = new Consumer("C1", queue, CAPACITY);
        Thread consumer2 = new Consumer("C2", queue, CAPACITY);
        Thread consumer3 = new Consumer("C3", queue, CAPACITY);

        producer1.start();
        producer2.start();
        consumer1.start();
        consumer2.start();
        consumer3.start();
    }

    /**
     * 生产者
     */
    public static class Producer extends Thread{
        private Queue<Integer> queue;
        String name;
        int maxSize;
        int i = 0;

        public Producer(String name, Queue<Integer> queue, int maxSize){
            super(name);
            this.name = name;
            this.queue = queue;
            this.maxSize = maxSize;
        }

        @Override
        public void run(){
            while(true){
                synchronized(queue){
                    while(queue.size() == maxSize){
                        try {
                            System.out .println("Queue is full, Producer[" + name + "] thread waiting for " + "consumer to take something from queue.");
                            queue.wait();
                        } catch (Exception ex) {
                            ex.printStackTrace();
                        }
                    }
                    System.out.println("[" + name + "] Producing value : +" + i);
                    queue.offer(i++);
                    queue.notifyAll();

                    try {
                        Thread.sleep(new Random().nextInt(1000));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }

        }
    }

    /**
     * 消费者
     */
    public static class Consumer extends Thread{
        private Queue<Integer> queue;
        String name;
        int maxSize;

        public Consumer(String name, Queue<Integer> queue, int maxSize){
            super(name);
            this.name = name;
            this.queue = queue;
            this.maxSize = maxSize;
        }

        @Override
        public void run(){
            while(true){
                synchronized(queue){
                    while(queue.isEmpty()){
                        try {
                            System.out.println("Queue is empty, Consumer[" + name + "] thread is waiting for Producer");
                            queue.wait();
                        } catch (Exception ex) {
                            ex.printStackTrace();
                        }
                    }
                    int x = queue.poll();
                    System.out.println("[" + name + "] Consuming value : " + x);
                    queue.notifyAll();

                    try {
                        Thread.sleep(new Random().nextInt(1000));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

 

/**
 * 生产者消费者模式:使用Lock和Condition实现
 * {@link java.util.concurrent.locks.Lock}
 * {@link java.util.concurrent.locks.Condition}
 */
public class ProducerConsumerByLock {
    private static final int CAPACITY = 5;
    private static final Lock lock = new ReentrantLock();
    private static final Condition fullCondition = lock.newCondition();     //队列满的条件
    private static final Condition emptyCondition = lock.newCondition();        //队列空的条件


    public static void main(String args[]){
        Queue<Integer> queue = new LinkedList<Integer>();

        Thread producer1 = new Producer("P-1", queue, CAPACITY);
        Thread producer2 = new Producer("P-2", queue, CAPACITY);
        Thread consumer1 = new Consumer("C1", queue, CAPACITY);
        Thread consumer2 = new Consumer("C2", queue, CAPACITY);
        Thread consumer3 = new Consumer("C3", queue, CAPACITY);

        producer1.start();
        producer2.start();
        consumer1.start();
        consumer2.start();
        consumer3.start();
    }

    /**
     * 生产者
     */
    public static class Producer extends Thread{
        private Queue<Integer> queue;
        String name;
        int maxSize;
        int i = 0;

        public Producer(String name, Queue<Integer> queue, int maxSize){
            super(name);
            this.name = name;
            this.queue = queue;
            this.maxSize = maxSize;
        }

        @Override
        public void run(){
            while(true){

                //获得锁
                lock.lock();
                while(queue.size() == maxSize){
                    try {
                        System.out .println("Queue is full, Producer[" + name + "] thread waiting for " + "consumer to take something from queue.");
                        //条件不满足,生产阻塞
                        fullCondition.await();
                    } catch (InterruptedException ex) {
                        ex.printStackTrace();
                    }
                }
                System.out.println("[" + name + "] Producing value : +" + i);
                queue.offer(i++);

                //唤醒其他所有生产者、消费者
                fullCondition.signalAll();
                emptyCondition.signalAll();

                //释放锁
                lock.unlock();

                try {
                    Thread.sleep(new Random().nextInt(1000));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }
    }

    /**
     * 消费者
     */
    public static class Consumer extends Thread{
        private Queue<Integer> queue;
        String name;
        int maxSize;

        public Consumer(String name, Queue<Integer> queue, int maxSize){
            super(name);
            this.name = name;
            this.queue = queue;
            this.maxSize = maxSize;
        }

        @Override
        public void run(){
            while(true){
                //获得锁
                lock.lock();

                while(queue.isEmpty()){
                    try {
                        System.out.println("Queue is empty, Consumer[" + name + "] thread is waiting for Producer");
                        //条件不满足,消费阻塞
                        emptyCondition.await();
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }
                int x = queue.poll();
                System.out.println("[" + name + "] Consuming value : " + x);

                //唤醒其他所有生产者、消费者
                fullCondition.signalAll();
                emptyCondition.signalAll();

                //释放锁
                lock.unlock();

                try {
                    Thread.sleep(new Random().nextInt(1000));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

 

基本功能 2016/10/31 添加抽奖功能,修复已知Bug(点击删除购物,出现闪退bug) 2016/10/28 添加微信分享功能 2016/10/28 添加忘记密码功能、完善用户评价系统、以及完善订单页面按钮功能及显示 2016/10/27 添加自动更新功能,修复已知的登陆闪退Bug 2016/10/26 添加订单查询(全部订单、待付款、待发货、待收货、待评价、退款和售后等查询)以及显示功能,收藏宝贝查询、及显示功能 2016/10/25 添加加入购物车功能、移除购物车中的商品和下单之后更新购物车等功能 2016/10/24 添加评论功能的显示、登陆用户的收藏和取消收藏功能、下单页面的显示、以及下单功能的实现 2016/10/23 添加商品的类别显示、分类查询展示、固定数据的搜索(暂时数据固定) 2016/10/22 添加用户注销功能、头像的上传以及更新用户个人资料功能 2016/10/20 添加注册、登陆、加载默认头像等功能、解决ViewPager Fragment 中Fragment被预加载问 2016/10/19 进行主页、微淘、问大家、购物车、我的淘宝等页面的设计、添加轮播图、资讯滚动条功能 2016/10/18 构建基本MVP框架 开发过程中遇到的问题(可能导致程序无法运行的bug)及解决方案 当用户未登录时,点击购物车,登陆之后,程序闪退 出现问题 :NullPointerException 解决方案: 使用Fragment的延时加载(懒加载)实现对数据的加载 拍照时无法进行图片的裁剪(不断加载) 解决步骤如下: Activity跳转时图库时的Intent如下 Intent takePhotoIntent = new Intent( “android.media.action.IMAGE_CAPTURE”); takePhotoIntent.putExtra( MediaStore.EXTRA_OUTPUT, imageUri); 在onActivityResult()方法中调用P层进行处理,相关代码如下 String uri = Environment.getExternalStorageDirectory() “/icoImage.jpg”; if(!allSelectedPicture.contains(uri)){ allSelectedPicture.add(uri); } ViewPager和Fragment结合使用,Fragment出现被预计载的情况 解决方案 项目中使用的主要技术及框架 框架 ButterKnife 注解绑定获取控件功能 Picasso 网络和本地图片的加载功能 okhttp 网络连接功能
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值