Service 两种启动方式

1.Context.startService()方式启动

Context.startService()方式的生命周期:

启动时,startService–>onCreate()–>onStart()

停止时,stopService– > onDestroy()

如果调用者直接退出而没有停止Service,

则Service会一直在后台运行Context.startService()方法启动服务。

在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onStart()方法。

如果调用startService()方法前服务已经被创建,

多次调用startService()方法并不会导致多次创建服务,

但会导致多次调用onStart()方法。

采用startService()方法启动的服务,

只能调用Context.stopService()方法结束服务,

服务结束时会调用onDestroy()方法。

2.Context.bindService()方式启动


Context.bindService()方式的生命周期:绑定时,

bindService->onCreate()–>onBind()调用者退出了,即解绑定时,

Srevice就会unbindService–>onUnbind()–>onDestory() 

Context.bindService()方式启动Service的方法:

绑定Service需要三个参数:bindService(intent, conn, Service.BIND_AUTO_CREATE);

第一个:Intent对象

第二个:ServiceConnection对象,创建该对象要实现它的onServiceConnected()和onServiceDisconnected()来判断连接成功或者是断开连接

第三个:如何创建Service,一般指定绑定的时候自动创建附代码

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import com.dada.test.BindService.MyBinder;
public class TestActivity extends Activity {
    private boolean flag;
    private static final String TAG = "TestActivity";
    /** Called when the activity is first created. */
    @Override public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Button btnStart = (Button) findViewById(R.id.btnStart);
        Button btnStop = (Button) findViewById(R.id.btnStop);
        btnStart.setOnClickListener(new View.OnClickListener() {@Override public void onClick(View v) {
                //启动service 方式2  
                bindService();
            }
        });
        btnStop.setOnClickListener(new View.OnClickListener() {
            @Override public void onClick(View v) {
                //停止service 方式2  
                unBindService();
            }
        });
    }
    //启动service 方式2  
    //  
    private void bindService() {
        Intent intent = new Intent(TestActivity.this, BindService.class);
        Log.i(TAG, "bindService()");
        bindService(intent, conn, Context.BIND_AUTO_CREATE);
    }
    private void unBindService() {
        Log.i(TAG, "unBindService() start....");
        if (flag == true) {
            Log.i(TAG, "unBindService() flag");
            unbindService(conn);
            flag = false;
        }
    }
    private ServiceConnection conn = new ServiceConnection() {
        @Override public void onServiceDisconnected(ComponentName name) {
            // TODO Auto-generated method stub  
            Log.i(TAG, "onServiceDisconnected()");
        }
        @Override public void onServiceConnected(ComponentName name, IBinder service) {
            // TODO Auto-generated method stub  
            Log.i(TAG, "onServiceConnected()");
            MyBinder binder = (MyBinder) service;
            BindService bindService = binder.getService1();
            bindService.MyMethod();
            flag = true;
        }
    };
}

service:

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
public class BindService extends Service {
    private static final String TAG = "BindService";
    private MyBinder myBinder = new MyBinder();
    public void MyMethod() {
        Log.i(TAG, "BindService-->MyMethod()");
    }
    
    @Override public IBinder onBind(Intent intent) {
        Log.i(TAG, "BindService-->onBind()");
        return myBinder;
    }
    
    public class MyBinder extends Binder {
        public BindService getService1() {
            return BindService.this;
        }
    }
    
    @Override public void onCreate() {
        Log.i(TAG, "BindService-->onCreate()");
        super.onCreate();
    }
    @Override public void onStart(Intent intent, int startId) {
        Log.i(TAG, "BindService-->onStart()");
        super.onStart(intent, startId);
    }
    @Override public void onDestroy() {
        Log.i(TAG, "BindService-->onDestroy()");
        super.onDestroy();
    }
    @Override public boolean onUnbind(Intent intent) {
        Log.i(TAG, "BindService-->onUnbind()");
        return super.onUnbind(intent);
    }
}

运行日志点击启动

点击停止

没有打出onServiceDisconnected的日志的原因:

注:SDK上是这么说的:This is called when the connection with the service has been unexpectedly disconnected–that is,

its process crashed.Because it is running in our same process,

we should never see this happen.

所以说,只有在service因异常而断开连接的时候,这个方法才会用到

其他

由于Service的onStart()方法只有在startService()启动Service的情况下才调用,故使用onStart()的时候要注意这点。

与Service通信并且让它持续运行如果我们想保持和Service的通信,又不想让Service随着Activity退出而退出呢?

你可以先startService()然后再bindService()。

当你不需要绑定的时候就执行unbindService()方法,执行这个方法只会触发Service的onUnbind()而不会把这个Service销毁。

这样就可以既保持和Service的通信,也不会随着Activity销毁而销毁了。

java中的匿名内部类总结

匿名内部类也就是没有名字的内部类

正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写

但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口

实例1 : 不使用匿名内部类来实现抽象方法

abstract class Person {
    public abstract void eat();
}

class Child extends Person {
    public void eat() {
        System.out.println("eat something");
    }
}

public class Demo {
    public static void main(String[] args) {
        Person p = new Child();
        p.eat();
    }
}

运行结果:eat something

可以看到,我们用Child继承了Person类,然后实现了Child的一个实例,将其向上转型为Person类的引用

但是,如果此处的Child类只使用一次,那么将其编写为独立的一个类岂不是很麻烦?

这个时候就引入了匿名内部类

实例2:匿名内部类的基本实现

abstract class Person {
    public abstract void eat();
}

public class Demo {
    public static void main(String[] args) {
        Person p = new Person() {
            public void eat() {
                System.out.println("eat something");
            }
        };
        p.eat();
    }
}

运行结果:eat something

可以看到,我们直接将抽象类Person中的方法在大括号中实现了

这样便可以省略一个类的书写

并且,匿名内部类还能用于接口上

实例3:在接口上使用匿名内部类

interface Person {
    public void eat();
}
public class Demo {
    public static void main(String[] args) {
        Person p = new Person() {
            public void eat() {
                System.out.println("eat something");
            }
        };
        p.eat();
    }
}

运行结果:eat something

由上面的例子可以看出,只要一个类是抽象的或是一个接口,那么其子类中的方法都可以使用匿名内部类来实现

最常用的情况就是在多线程的实现上,因为要实现多线程必须继承Thread类或是继承Runnable接口

实例4:Thread类的匿名内部类实现

public class Demo {
    public static void main(String[] args) {
        Thread t = new Thread() {
            public void run() {
                for (int i = 1; i <= 5; i++) {
                    System.out.print(i + " ");
                }
            }
        };
        t.start();
    }
}

运行结果:1 2 3 4 5

实例5:Runnable接口的匿名内部类实现

public class Demo {
    public static void main(String[] args) {
        Runnable r = new Runnable() {
            public void run() {
                for (int i = 1; i <= 5; i++) {
                    System.out.print(i + " ");
                }
            }
        };
        Thread t = new Thread(r);
        t.start();
    }
}

向下转型

在学习Android的时候 书里提到了向下转型

对java不熟悉的我又要补课了

这篇博客就是讲向下转型的,那我们就来学习下向下转型,了解下这种特性的意义和使用场景

新建一个电子产品接口,如下:

public interface Electronics{

}

很简单,什么方法都没有。

新建一个Thinkpad笔记本类,并实现电子产品接口:

public class Thinkpad implements Electronics {

    //Thinkpad引导方法
    public void boot() {
        System.out.println("welcome,I am Thinkpad");
    }

    //使用Thinkpad编程  
    public void program() {
        System.out.println("using Thinkpad program");
    }

}

新建一个Mouse鼠标类,并实现电子产品接口:

public class Mouse implements Electronics{

    //鼠标移动
    public void move(){
        System.out.println("move the mouse");       
    }    //鼠标点击  
    public void onClick(){
        System.out.println("a click of the mouse");
    }

}

新建一个Keyboard键盘类,并实现电子产品接口:

public class Keyboard implements Electronics{

    //使用键盘输入    
    public void input(){
        System.out.println("using Keyboard input");
    }

}

这里子类比较多,是为了更好的理解。每个类的方法的逻辑实现也很简单。打印了一行信息

接下来,我们想象一个情景:我们去商城买电子产品,电子产品很多吧,比如笔记本电脑,鼠标,键盘,步步高点读机哪里不会点哪里,我们用的手机,等等,这些都属于电子产品。

电子产品是抽象的。

好,那么我们决定买一台Thinkpad,一个鼠标和一个键盘。

这时,我们需要一个购物车来装这些电子产品吧。

我们可以添加进购物车,然后通过购物车还能知道存放的电子产品数量,能拿到对应的电子产品。

那么,一个购物车类就出来了,如下:

import java.util.ArrayList;
import java.util.List;

public class ShopCar {

    private List < Electronics > mlist = new ArrayList < Electronics > ();

    public void add(Electronics electronics) {

        mlist.add(electronics);

    }

    public int getSize() {

        return mlist.size();
    }

    public Electronics getListItem(int position) {

        return mlist.get(position);

    }

}

List集合是用来存放电子产品的,add方法用来添加电子产品到购物车,getSize方法用来获取存放的电子产品数量,getListItem方法用来获取相应的电子产品。

可以看到List < Electronics > 用了泛型的知识,至于为什么要用泛型?

这个不做介绍了,泛型很重要的。

而我觉得比较疑惑的是为什么是放Electronics的泛型,而不是放Thinkpad,Mouse,Keyboard,Phone等?

那么如果是List < Thinkpad > ,肯定是放不进鼠标Mouse的吧,难道要生成3个集合?

这里是定义了3个电子产品类,但是我如果有100种电子产品呢,要定义100个集合 ? 

这太可怕了。

所以之前,我们写了一个Electronics接口,提供了一个Electronics的标准,然后让每一个Electronics子类都去实现这个接口。

实际上这里又涉及到了向上转型的知识点,我们虽然在add方法将子类实例传了进来存放,但子类实例在传进去的过程中也进行了向上转型所以,此时购物车里存放的子类实例对象,由于向上转型成Electronics,已经丢失了子类独有的方法,以上述例子来分析,Thinkpad实例就是丢失了boot()和program()这两个方法,而Mouse实例就是丢失了move()和onClick()这两个方法

但是实际使用Thinkpad或Mouse或Keyboard时,这种情况肯定不是我们想要的

接着我们写一个测试类Test去测试购物车里的电子产品。

测试类Test如下:

public class Test {

    public static final int THINKPAD = 0;
    public static final int MOUSE = 1;
    public static final int KEYBOARD = 2;

    public static void main(String[] args) {

        //添加进购物车
        ShopCar shopcar = new ShopCar();
        shopcar.add(new Thinkpad());
        shopcar.add(new Mouse());
        shopcar.add(new Keyboard());

        //获取大小
        System.out.println("购物车存放的电子产品数量为 ——> " + shopcar.getSize());

        //开始测试thinkpad电脑
        Thinkpad thinkpad = (Thinkpad) shopcar.getListItem(THINKPAD);
        thinkpad.boot();
        thinkpad.program();

        System.out.println("-------------------");

        //开始测试Mouse鼠标
        Mouse mouse = (Mouse) shopcar.getListItem(MOUSE);
        mouse.move();
        mouse.onClick();

        System.out.println("-------------------");

        //开始测试Keyboard键盘
        Keyboard keyboard = (Keyboard) shopcar.getListItem(KEYBOARD);
        keyboard.input();
    }

}

运行截图:

20161022214436745.png

举个例子分析就好

//开始测试thinkpad电脑
Thinkpad thinkpad = (Thinkpad)shopcar.getListItem(THINKPAD);
thinkpad.boot();
thinkpad.program();

shopcar.getListItem(THINKPAD)这句代码是获取到Electronics类型的实例。不是Thinkpad的实例

通过向下转型,赋值给子类引用

Thinkpad thinkpad = (Thinkpad) shopcar.getListItem(THINKPAD);

这样子类实例又重新获得了因为向上转型而丢失的方法(boot和program)

总结一下吧,很多时候,我们需要把很多种类的实例对象,全部扔到一个集合。(这句话很重要)

在这个例子里就是把Thinkpad笔记本,Mouse鼠标,KeyBoard键盘等实例对象,全部扔到一个Shopcar购物车集合。

但是肯定不可能给他们每个种类都用一个独立的集合去存放吧,这个时候我们应该寻找到一个标准,接口就是一个标准。这些都是各种电子产品,抽象成电子产品。

然后一个Electronics接口就出来了。

在回到刚才,我们把很多种类的实例对象全部扔到一个集合。

或许这样比较好理解:把很多种类的子类实例对象全部扔到存放父类实例的集合。

经过了这个过程,子类实例已经赋值给了父类引用(即完成了向上转型),但很遗憾的丢失了子类扩展的方法。

很好的是Java语言有个向下转型的特性,让我们可以重新获得丢失的方法,即强转回子类所以我们需要用到子类实例的时候,就从那个父类集合里拿出来向下转型就可以了,一样可以使用子类实例对象……

我在搜索java向下转型的意义时,得到一个比较好的答案是这样的:最大的用处是java的泛型编程,用处很大,Java的集合类都是这样的。

而在Android开发中,我们在Layout文件夹,用xml写的控件。为什么能在Activity等组件中通过findViewById()方法找到呢?

为什么findViewById(R.id.textview)方法传入TextView的id后,还要转型为TextView呢?

这就是Java向下转型的一个应用。

JAVA 向上/向下转型

向上转型


我们在现实中常常这样说:这个人会唱歌。

在这里,我们并不关心这个人是黑人还是白人,

是成人还是小孩,也就是说我们更倾向于使用抽象概念“人”。

再例如,麻雀是鸟类的一种(鸟类的子类),

而鸟类则是动物中的一种(动物的子类)。

我们现实中也经常这样说:麻雀是鸟。

这两种说法实际上就是所谓的向上转型,

通俗地说就是子类转型成父类。

这也符合Java提倡的面向抽象编程思想。来看下面的代码:

package a.b;
public class A {
    public void a1() {
        System.out.println("Superclass");
    }
}


A的子类B:

package a.b;

public class B extends A {

    public void a1() {

        System.out.println("Childrenclass"); //覆盖父类方法
    }

    public void b1() {} //B类定义了自己的新方法
}


C类:

package a.b;

public class C {

    public static void main(String[] args) {

        A a = new B(); //向上转型
        a.a1();

    }

}


如果运行C,输出的是Superclass 还是Childrenclass?

不是你原来预期的Superclass,而是Childrenclass。

这是因为a实际上指向的是一个子类对象。

当然,你不用担心,Java虚拟机会自动准确地识别出究竟该调用哪个具体的方法。

不过,由于向上转型,a对象会遗失和父类不同的方法,例如b1()。

有人可能会提出疑问:这不是多此一举吗?我们完全可以这样写:

B a = new B();

a.a1();


确实如此!但这样就丧失了面向抽象的编程特色,降低了可扩展性。其实,不仅仅如此,向上转型还可以减轻编程工作量。

来看下面的显示器类Monitor:

package a.b;

public class Monitor {

    public void displayText() {}

    public void displayGraphics() {}

}


液晶显示器类LCDMonitor是Monitor的子类:

package a.b;

public class LCDMonitor extends Monitor {

    public void displayText() {

        System.out.println("LCD display text");

    }

    public void displayGraphics() {

        System.out.println("LCD display graphics");

    }

}


阴极射线管显示器类CRTMonitor自然也是Monitor的子类:

package a.b;

public class CRTMonitor extends Monitor {

    public void displayText() {

        System.out.println("CRT display text");

    }

    public void displayGraphics() {

        System.out.println("CRT display graphics");

    }

}


等离子显示器PlasmaMonitor也是Monitor的子类:

package a.b;

public class PlasmaMonitor extends Monitor {

    public void displayText() {

        System.out.println("Plasma display text");

    }

    public void displayGraphics() {

        System.out.println("Plasma display graphics");

    }

}


现在有一个MyMonitor类。假设没有向上转型,MyMonitor类代码如下:

package a.b;

public class MyMonitor {

    public static void main(String[] args) {

        run(new LCDMonitor());

        run(new CRTMonitor());

        run(new PlasmaMonitor());

    }

    public static void run(LCDMonitor monitor) {

        monitor.displayText();

        monitor.displayGraphics();

    }

    public static void run(CRTMonitor monitor) {

        monitor.displayText();

        monitor.displayGraphics();

    }

    public static void run(PlasmaMonitor monitor) {

        monitor.displayText();

        monitor.displayGraphics();

    }

}


可能你已经意识到上述代码有很多重复代码,而且也不易维护。有了向上转型,代码可以更为简洁:

package a.b;

public class MyMonitor {

    public static void main(String[] args) {

        run(new LCDMonitor()); //向上转型
        run(new CRTMonitor()); //向上转型
        run(new PlasmaMonitor()); //向上转型
    }

    public static void run(Monitor monitor) { //父类实例作为参数
        monitor.displayText();

        monitor.displayGraphics();

    }

}

向下转型


子类转型成父类是向上转型,反过来说,父类转型成子类就是向下转型。

但是,向下转型可能会带来一些问题:我们可以说麻雀是鸟,但不能说鸟就是麻雀。来看下面的例子:


A类:

package a.b;

public class A {

    void aMthod() {

        System.out.println("A method");

    }

}

A的子类B:

package a.b;

public class B extends A {

    void bMethod1() {

        System.out.println("B method 1");

    }

    void bMethod2() {

        System.out.println("B method 2");

    }

}

C类:

package a.b;

public class C {
    public static void main(String[] args) {
        A a1 = new B(); // 向上转型
        a1.aMthod(); // 调用父类aMthod(),a1遗失B类方法bMethod1()、bMethod2()
        
        B b1 = (B) a1; // 向下转型,编译无错误,运行时无错误
        b1.aMthod(); // 调用父类A方法
        b1.bMethod1(); // 调用B类方法
        b1.bMethod2(); // 调用B类方法
        
        A a2 = new A();
        B b2 = (B) a2; // 向下转型,编译无错误,运行时将出错
        b2.aMthod();
        b2.bMethod1();
        b2.bMethod2();
    }

}


从上面的代码我们可以得出这样一个结论:向下转型需要使用强制转换。

运行C程序,控制台将输出:

Exception in thread "main"java.lang.ClassCastException: a.b.A cannot be cast to a.b.B at a.b.C.main(C.java: 14)

A method

A method

B method 1

B method 2

其实黑体部分的向下转型代码后的注释已经提示你将发生运行时错误。

为什么前一句向下转型代码可以,而后一句代码却出错?

这是因为a1指向一个子类B的对象,

所以子类B的实例对象b1当然也可以指向a1。

而a2是一个父类对象,子类对象b2不能指向父类对象a2。

那么如何避免在执行向下转型时发生运行时ClassCastException异常?

使用instanceof就可以了。

我们修改一下C类的代码:

A a2 = new A();

if (a2 instanceof B) {

    B b2 = (B) a2;

    b2.aMthod();

    b2.bMethod1();

    b2.bMethod2();

}

这样处理后,就不用担心类型转换时发生ClassCastException异常了。

public IBinder onBind(Intent intent) { 关于此处的IBinder

在Android中Service的启动方式有两种,第一种是startService,第二种是bindService. 这里问的是第二种方法,生命周期是这样的:

bindSerivce->onCreate->onBind->running->onUnbind->onDestroy. 
由字面意思可以看出来onBind方法就是当试图绑定服务时做的事,
作用一般情况下主要是返回IBinder对象,
为后面服务成功绑定时的操作做准备,
也可以做一些服务初始化之类的事。
如果用过bindService就会知道这个方法里的第二个参数是一个ServiceConnection的对象,
在使用这个对象的时候需要重写两个方法
onServiceConnected(ComponentName name, IBinder service) 
和 
onServiceDisconnected(ComponentName name). 

其中onServiceConnected方法参数中的service就是你上面所说的返回的IBinder的对象,
,
说明服务成功绑定,而在这个方法里面你可以对服务中的一些数据进行初始化控制等操作,
实现Activity与Service之间简单的交互。

参照网上资料把Service的两种启动方式所涉及到的知识点梳理一遍,
然后再编程调试,
可以加深对这一部分知识的理解。

android AsyncTask

最近用到的 AsyncTask记录一下

AsyncTask和Handler对比

1 ) AsyncTask实现的原理,和适用的优缺点

AsyncTask,是android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,提供接口反馈当前异步执行的程度(可以通过接口实现UI进度更新),最后反馈执行的结果给UI主线程.

使用的优点:

l  简单,快捷

l  过程可控

       

使用的缺点:

l  在使用多个异步操作和并需要进行Ui变更时,就变得复杂起来.

2 )Handler异步实现的原理和适用的优缺点

在Handler 异步实现时,涉及到 Handler, Looper, Message,Thread四个对象,实现异步的流程是主线程启动Thread(子线程)àthread(子线程)运行并生成Message-àLooper获取Message并传递给HandleràHandler逐个获取Looper中的Message,并进行UI变更。

使用的优点:

l  结构清晰,功能定义明确

l  对于多个后台任务时,简单,清晰

   

使用的缺点:

l  在单个后台异步处理时,显得代码过多,结构过于复杂(相对性)

 

AsyncTask介绍

Android的AsyncTask比Handler更轻量级一些,适用于简单的异步处理。

首先明确Android之所以有Handler和AsyncTask,都是为了不阻塞主线程(UI线程),且UI的更新只能在主线程中完成,因此异步处理是不可避免的。

 

Android为了降低这个开发难度,提供了AsyncTask。AsyncTask就是一个封装过的后台任务类,顾名思义就是异步任务。

AsyncTask直接继承于Object类,位置为android.os.AsyncTask。要使用AsyncTask工作我们要提供三个泛型参数,并重载几个方法(至少重载一个)。

 

AsyncTask定义了三种泛型类型 Params,Progress和Result。

  • Params 启动任务执行的输入参数,比如HTTP请求的URL。

  • Progress 后台任务执行的百分比。

  • Result 后台执行任务最终返回的结果,比如String。

使用过AsyncTask 的同学都知道一个异步加载数据最少要重写以下这两个方法:

  • doInBackground(Params…) 后台执行,比较耗时的操作都可以放在这里。注意这里不能直接操作UI。此方法在后台线程执行,完成任务的主要工作,通常需要较长的时间。在执行过程中可以调用publicProgress(Progress…)来更新任务的进度。

  • onPostExecute(Result)  相当于Handler 处理UI的方式,在这里面可以使用在doInBackground 得到的结果处理操作UI。 此方法在主线程执行,任务执行的结果作为此方法的参数返回

有必要的话你还得重写以下这三个方法,但不是必须的:

  • onProgressUpdate(Progress…)   可以使用进度条增加用户体验度。 此方法在主线程执行,用于显示任务执行的进度。

  • onPreExecute()        这里是最终用户调用Excute时的接口,当任务执行之前开始调用此方法,可以在这里显示进度对话框。

  • onCancelled()             用户调用取消时,要做的操作

使用AsyncTask类,以下是几条必须遵守的准则:

  • Task的实例必须在UI thread中创建;

  • execute方法必须在UI thread中调用;

  • 不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params…), onProgressUpdate(Progress…)这几个方法;

  • 该task只能被执行一次,否则多次调用时将会出现异常;

一个超简单的理解 AsyncTask 的例子:

main.xml

<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:orientation="vertical"  
    android:layout_width="fill_parent"  
    android:layout_height="fill_parent"  
    >  
    <TextView    
    android:id="@+id/textView01"  
    android:layout_width="fill_parent"   
    android:layout_height="wrap_content"   
    />  
   <ProgressBar   
   android:id="@+id/progressBar02"  
    android:layout_width="fill_parent"   
    android:layout_height="wrap_content"   
    style="?android:attr/progressBarStyleHorizontal"   
    />  
    <Button  
    android:id="@+id/button03"  
    android:layout_width="fill_parent"   
    android:layout_height="wrap_content"   
    android:text="更新progressbar"  
    />  
</LinearLayout>

MainActivity.java

package vic.wong.main;  
  
import android.app.Activity;  
import android.os.Bundle;  
import android.view.View;  
import android.view.View.OnClickListener;  
import android.widget.Button;  
import android.widget.ProgressBar;  
import android.widget.TextView;  
  
public class MainActivity extends Activity {  
    private Button button;  
    private ProgressBar progressBar;  
    private TextView textView;  
      
    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);  
          
        button = (Button)findViewById(R.id.button03);  
        progressBar = (ProgressBar)findViewById(R.id.progressBar02);  
        textView = (TextView)findViewById(R.id.textView01);  
          
        button.setOnClickListener(new OnClickListener() {  
              
            @Override  
            public void onClick(View v) {  
                ProgressBarAsyncTask asyncTask = new ProgressBarAsyncTask(textView, progressBar);  
                asyncTask.execute(1000);  
            }  
        });  
    }  
}

NetOperator.java

package vic.wong.main;  
  
  
//模拟网络环境  
public class NetOperator {  
      
    public void operator(){  
        try {  
            //休眠1秒  
            Thread.sleep(1000);  
        } catch (InterruptedException e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        }  
    }  
  
}

ProgressBarAsyncTask .java 

package vic.wong.main;  
import android.os.AsyncTask;  
import android.widget.ProgressBar;  
import android.widget.TextView;  
  
/**  
 * 生成该类的对象,并调用execute方法之后  
 * 首先执行的是onProExecute方法  
 * 其次执行doInBackgroup方法  
 *  
 */  
public class ProgressBarAsyncTask extends AsyncTask<Integer, Integer, String> {  
  
    private TextView textView;  
    private ProgressBar progressBar;  
      
      
    public ProgressBarAsyncTask(TextView textView, ProgressBar progressBar) {  
        super();  
        this.textView = textView;  
        this.progressBar = progressBar;  
    }  
  
  
    /**  
     * 这里的Integer参数对应AsyncTask中的第一个参数   
     * 这里的String返回值对应AsyncTask的第三个参数  
     * 该方法并不运行在UI线程当中,主要用于异步操作,所有在该方法中不能对UI当中的空间进行设置和修改  
     * 但是可以调用publishProgress方法触发onProgressUpdate对UI进行操作  
     */  
    @Override  
    protected String doInBackground(Integer... params) {  
        NetOperator netOperator = new NetOperator();  
        int i = 0;  
        for (i = 10; i <= 100; i+=10) {  
            netOperator.operator();  
            publishProgress(i);  
        }  
        return i + params[0].intValue() + "";  
    }  
  
  
    /**  
     * 这里的String参数对应AsyncTask中的第三个参数(也就是接收doInBackground的返回值)  
     * 在doInBackground方法执行结束之后在运行,并且运行在UI线程当中 可以对UI空间进行设置  
     */  
    @Override  
    protected void onPostExecute(String result) {  
        textView.setText("异步操作执行结束" + result);  
    }  
  
  
    //该方法运行在UI线程当中,并且运行在UI线程当中 可以对UI空间进行设置  
    @Override  
    protected void onPreExecute() {  
        textView.setText("开始执行异步线程");  
    }  
  
  
    /**  
     * 这里的Intege参数对应AsyncTask中的第二个参数  
     * 在doInBackground方法当中,,每次调用publishProgress方法都会触发onProgressUpdate执行  
     * onProgressUpdate是在UI线程中执行,所有可以对UI空间进行操作  
     */  
    @Override  
    protected void onProgressUpdate(Integer... values) {  
        int vlaue = values[0];  
        progressBar.setProgress(vlaue);  
    }   
}

PhpStorm/IDEA/clion/pycharm 的破解与激活

安装完软件后,启动,在要求输入注册码的界面(菜单栏 ⇒ help ⇒ register)选择“License server”输入“http://idea.lanyus.com/”点击“OK”快速激活。

如果这种方式破解,点击 OK 按钮之后,出现红色错误提示:License Server response haven’t passed data integrity check:Server hijacked ?

则在浏览器的地址栏输入:http://idea.lanyus.com/,该网址,无需修改用户名,点击获取注册码。复制该注册码,粘贴在注册界面的 Activation code的输入框中,点击 ok。