新浪微盘2


2.新浪微盘授权登录完成


1.微盘开发平台 :http://vdisk.weibo.com/developers/
  (1)创建新应用
  (2)与新浪微博授权一样
  (3)获得appkey和appscr...


2.完成登录----第三方登录
(1)布局:

<RelativeLayout 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"
    tools:context=".LoginActivity" >

    <Button
        android:id="@+id/btnLogin"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="点击授权" />

</RelativeLayout>



(2)查看官方demo,开发文档


(3)关联lib或jar包


(4)配置文件


权限:

<uses-permission android:name="android.permission.INTERNET" >
    </uses-permission>
    <uses-permission android:name="android.permission.READ_PHONE_STATE" >
    </uses-permission>
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" >
    </uses-permission>
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" >
    </uses-permission>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" >
    </uses-permission>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />



 (5)登录代码

public class LoginActivity extends Activity implements VDiskDialogListener {
 /*--- 以下的 CONSUMER_KEY CONSUMER_SECRET REDIRECT_URL 是老师申请的.没有basic权限,不能直接反问目录.为了继续往下写,所以使用demo里面的这个几个东西---------------*/
 /*public static final String CONSUMER_KEY = "3237555059";
 public static final String CONSUMER_SECRET = "2b6c964b071e2ecc28c1835628cc6901";
 public static final String REDIRECT_URL = "http://billy.itheima.com";*/
 /*--------------- 以下的 CONSUMER_KEY CONSUMER_SECRET REDIRECT_URL 是apidemo里面的 ---------------*/
 public static final String CONSUMER_KEY = "2330724462";
 public static final String CONSUMER_SECRET = "04f81fc56cc936bfc8f0fa1cef285158";
 public static final String REDIRECT_URL = "http://vauth.appsina.com/callback1.php";
 private Button    mBtnLogin;
 private VDiskAuthSession session;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_login);
  init();
  initView();
  initData();
  initListener();
 }
 private void init() {
  /**
   * 初始化 Init
   */
  AppKeyPair appKeyPair = new AppKeyPair(CONSUMER_KEY, CONSUMER_SECRET);
  /**
   * @AccessType.APP_FOLDER - sandbox 模式
   * @AccessType.VDISK - basic 模式
   */
  session = VDiskAuthSession.getInstance(this, appKeyPair, AccessType.VDISK);
  // 如果session没有过期.我们就不需要再次授权.直接跳到主界面就可以了
  if (session.isLinked()) {// 未过期
   startActivity(new Intent(this, MainActivity.class));
   finish();
  }
 }
 private void initView() {
  mBtnLogin = (Button) findViewById(R.id.btnLogin);
 }
 private void initData() {
  // TODO
 }
 private void initListener() {
  mBtnLogin.setOnClickListener(new OnClickListener() {
   @Override
   public void onClick(View v) {
    // 使用微盘Token认证,需设置重定向网址
    // Need to set REDIRECT_URL if you want to use VDisk token.
    session.setRedirectUrl(REDIRECT_URL);
    // 1.发起授权请求-->让用户输入账号/密码
    session.authorize(LoginActivity.this, LoginActivity.this);
   }
  });
 }
 /*===============  2.处理授权的结果-->得到accessToken ===============*/
 @Override
 public void onComplete(Bundle values) {// 授权完成
  if (values != null) {
   AccessToken mToken = (AccessToken) values.getSerializable(VDiskAuthSession.OAUTH2_TOKEN);
   session.finishAuthorize(mToken);// 把token绑定到session
   Toast.makeText(getApplicationContext(), mToken.getToken(), 0).show();
  }
  startActivity(new Intent(this, MainActivity.class));
  finish();
 }
 @Override
 public void onError(VDiskDialogError error) {// 授权错误
  // TODO
 }
 @Override
 public void onVDiskException(VDiskException exception) {// 授权异常
  // TODO
 }
 @Override
 public void onCancel() {// 授权取消
  // TODO
 }
}

 


 


3.通过微盘登录讲解oauth授权的3个步骤


1.点击了发起授权请求的按钮,也是oauth2.0授权步骤中的第一步,其实就是去打开了一个授权的网页
 https://auth.sina.com.cn/oauth2/authorize?client_id=3237555059&redirect_uri=http%3A%2F%2Fbilly.itheima.com&display=mobile


2.用户授权完成之后
 回调到回调页,同时传递code
 
http://billy.itheima.com/?code=ce97366666b1b902575ce207401477ff&state=


3.拿着授权的code请求accessToken
 请求地址:https://auth.sina.com.cn/oauth2/access_token
 请求方式:post
 请求参数的形式:key-value
 请求具体参数
 client_id=3237555059&client_secret=2b6c964b071e2ecc28c1835628cc6901&grant_type=authorization_code&code=ce97366666b1b902575ce207401477ff&redirect_uri=http%3A%2F%2Fbilly.itheima.com
 
     {
        "access_token": "26883566623yk3e3x6rXZ3gOj5J35b6d",
        "expires_in": 1437982314,
        "time_left": 22868,
        "uid": "1884774904",
        "refresh_token": "f244f166623yk3e3x6rXZ3gOj5Jf1bb7"
     }


4.使用accessToken访问个人信息
 https://api.weipan.cn/2/account/info?access_token=26883566623yk3e3x6rXZ3gOj5J35b6d
 
4.token的3层加密


1.jar包自动加密


2.des-->密码唯一化,复杂化(但是还是不安全)
 
 `this.PASSWORD = "com.sina.vdisk.security.password.d7af3082d815945ff47ae58647bd9436"
  + IMEI + appKeyPair.key + appKeyPair.secret;`

 

3.秘钥放到so库里面.通过jni调用-->密码放到so库里面.这个时候.加到了获取秘钥的难度.(同样,反编译apk,可以拿到so库,然后可以调用本地方法获取到密码)


4.混淆(也是可以拿到,混淆的时候.我们的字符串是不会进行混淆的.只是混淆我们方法名,以及变量名)


5.梆梆加固,爱加密的使用


1.防止apk反编译


2.梆梆加固:http://www.bangcle.com/
 (1).上传,签名工具


3.爱加密的使用


6.文件信息列表初步完成


1.参考官网sdk demo


2.数据来源


7.文件信息列表美化完成


1.ListView优化


  

@Override
  public View getView(int position, View convertView, ViewGroup parent) {
   ViewHolder holder;
   if (convertView == null) {
    convertView = MainActivity.this.getLayoutInflater().inflate(R.layout.file_item, null);

    holder = new ViewHolder();
    holder.tvName = (TextView) convertView.findViewById(R.id.tv_name);
    holder.tvTime = (TextView) convertView.findViewById(R.id.tv_time);
    holder.tvSize = (TextView) convertView.findViewById(R.id.tv_size);
    holder.ivIcon = (ImageView) convertView.findViewById(R.id.iv_icon);
    holder.ivOption = (ImageView) convertView.findViewById(R.id.iv_option);
    holder.cbCheck = (CheckBox) convertView.findViewById(R.id.cb_checkbox);

    convertView.setTag(holder);
   } else {
    holder = (ViewHolder) convertView.getTag();
   }
   // 得到数据
   // 设置数据
   Entry entry = mEntries.get(position);
   holder.tvName.setText(entry.fileName());
   holder.tvSize.setText(entry.size);

   Date parseDate = RESTUtility.parseDate(entry.modified);
   holder.tvTime.setText(Utils.getFormateTime(parseDate));

   if (entry.isDir) {// 如果是文件夹
    holder.ivIcon.setImageResource(R.drawable.directory_icon);
    // 隐藏大小显示
    holder.tvSize.setVisibility(8);
   } else {
    holder.tvSize.setVisibility(0);
    // 根据文件类型做不同的展示
    Object[] mimeType = Utils.getMIMEType(entry.fileName());
    // type = "image/*";
    // res[1] = R.drawable.picture_icon;
    // mimeType[0]-->mimetype
    // mimeType[1]-->就是mimeType对应应该显示的图片
    holder.ivIcon.setImageResource((Integer) mimeType[1]);
   }
   return convertView;
  }

  class ViewHolder {
   TextView tvName;
   TextView tvTime;
   TextView tvSize;

   ImageView ivIcon;
   ImageView ivOption;

   CheckBox cbCheck;
  }

 }


 

8.pulltofresh集成到文件信息列表中


1.pulltorefresh_lib_vdisk---------------lib包,包含listview,gridview等得下拉刷新
(1)关联lib包
(2)使用里面的自定义控件(如:listview)

 <RelativeLayout 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"
    tools:context=".LoginActivity" >

    <com.handmark.pulltorefresh.library.PullToRefreshListView
        android:background="#fff"
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

   </RelativeLayout>


 

  (3)

private PullToRefreshListView mPullToRefreshListView;

mPullToRefreshListView = (PullToRefreshListView) findViewById(R.id.listView);//本身继承linerlayout,不是listview
mListView = mPullToRefreshListView.getRefreshableView();//所以把lieanlayout中的孩子listview拿出来,才可以用适配器

mListView.setAdapter(mAdapter);
 // 加载数据的时候应该显示下载刷新中的视图
mPullToRefreshListView.setRefreshing();// 1. 显示正在加载的一个效果


// 2. 加载完成,关闭加载效果
mPullToRefreshListView.onRefreshComplete();


//下拉刷新
mPullToRefreshListView.setOnRefreshListener(new OnRefreshListener() {

   @Override
  public void onRefresh() {
   // 重新请求网络加载数据
    initData();

   }
 });
 
 
 // 刷新ui
mAdapter.notifyDataSetChanged();



 


 

 

9.xlistview的使用,SwipeRefreshLayout简介


1.xlistview只专注listview,属于lib包,需要关联


2.xlistview小demo
(1)关联lib包
(2)布局:

<RelativeLayout 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"
    tools:context=".MainActivity" >

    <me.maxwin.view.XListView
        android:id="@+id/xlv"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>



(3)MianActivity.java

public class MainActivity extends Activity {

 private XListView  mXlv;
 private List<String> mDatas  = new ArrayList<String>();
 private Handler   mHandler = new Handler() {
           public void handleMessage(android.os.Message msg) {
            if (isLoadMore) {// 如果是加载更多我就追加数据
             for (int i = 0; i < 50; i++) {
              String str = "我是第" + i + "条数据";
              mDatas.add(str);
             }
             isLoadMore = false;
             // 关闭加载更多的效果
             mXlv.stopLoadMore();
            } else {
             mDatas.clear();// 如果是下拉刷新.我就clean数据
             for (int i = 0; i < 50; i++) {
              String str = "我是第" + i + "条数据";
              mDatas.add(str);
             }
             // 关闭下拉刷新的效果
             mXlv.stopRefresh();
            }
            // 刷新listview
            mAdapter.notifyDataSetChanged();

           };
          };
 private boolean   isLoadMore;
 private MainAdapter  mAdapter;
 private long   mPreUpdateTime;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  mXlv = (XListView) findViewById(R.id.xlv);

  for (int i = 0; i < 50; i++) {
   String str = "我是第" + i + "条数据";
   mDatas.add(str);
  }

  mAdapter = new MainAdapter();
  mXlv.setAdapter(mAdapter);

  mXlv.setPullRefreshEnable(true);// 是否支持下拉刷新.默认是true
  mXlv.setPullLoadEnable(true);// 是否支持上拉加载更多.默认是false

  mXlv.setXListViewListener(new IXListViewListener() {

   @Override
   public void onRefresh() {// 下拉刷新
    mHandler.sendMessageDelayed(Message.obtain(), 2000);
    if (mPreUpdateTime != 0) {
     mXlv.setRefreshTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(mPreUpdateTime)));
    }
    mPreUpdateTime = System.currentTimeMillis();
    System.out.println("--onRefresh---");
   }

   @Override
   public void onLoadMore() {// 上拉加载更多
    isLoadMore = true;
    mHandler.sendMessageDelayed(Message.obtain(), 2000);
    System.out.println("--onLoadMore---");

   }
  });

 }

 class MainAdapter extends BaseAdapter {

  @Override
  public int getCount() {
   if (mDatas != null) {
    return mDatas.size();
   }
   return 0;
  }

  @Override
  public Object getItem(int position) {
   if (mDatas != null) {
    return mDatas.get(position);
   }
   return null;
  }

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

  @Override
  public View getView(int position, View convertView, ViewGroup parent) {
   TextView tv = new TextView(MainActivity.this);
   tv.setText(mDatas.get(position));
   return tv;
  }

 }
}


 

3.第三种下拉刷新:系统v4包自带--------------SwipeRefreshLayout  


4.第四种下拉刷新:系统自带5.0版本的v4包-------------也叫SwipeRefreshLayout

 


10.网络引擎的初步封装


11.网络引擎封装完成


1.position = position - mListView.getHeaderViewsCount();// 处理添加头之后的position问题


2.不通网络请求封装到CloudEngine.class中,以方法的形式暴露;


3.所有网络请求结果的处理.通过接口方法回调回来;


4.代码:


(1)CloudEngine.java

public class CloudEngine {
 public static CloudEngine instance;
 VDiskAPI<VDiskAuthSession> mApi;
 public static final int  REQ_FILE_LIST = 100;
 public static final int  REQ_FILE_DELETE = 101;
 Context      ctx;

 private CloudEngine(Context context) {
  // 在构造方法里面初始化一些访问api需要的类
  ctx = context;
  init(context);
 }

 private void init(Context context) {
  AppKeyPair appKeyPair = new AppKeyPair(LoginActivity.CONSUMER_KEY, LoginActivity.CONSUMER_SECRET);
  /**
     VDISK("basic"), APP_FOLDER("sandbox");
     
     //正式环境-->数据是真实
     //测试环境-->数据也是真实-->支付(1分钱)
   */
  VDiskAuthSession session = VDiskAuthSession.getInstance(context, appKeyPair, AccessType.VDISK);

  mApi = new VDiskAPI<VDiskAuthSession>(session);
 }
    //单例方法
 public static CloudEngine getInstance(Context context) {
  if (instance == null) {
   synchronized (CloudEngine.class) {
    if (instance == null) {
     instance = new CloudEngine(context);
    }
   }
  }
  return instance;
 }

 /**得到文件夹列表*/
 public void getFileList(IDataCallBack dataCallBack, int reqCode) {
  new FileListTask(dataCallBack, reqCode).execute();
 }

 /**删除文件*/
 public void deleteFile(IDataCallBack dataCallBack, String path, int reqCode) {
  new FileDeleteTask(dataCallBack, path, reqCode).execute();
 }

 class FileDeleteTask extends BaseTask {
  String mPath;

  public FileDeleteTask(IDataCallBack dataCallBack, String path, int reqCode) {
   super(dataCallBack, reqCode);
   mPath = path;
  }

  @Override
  protected Void doInBackground(Void... params) {
   // 真正的发起请求删除文件
   try {
    Entry deletedEntry = mApi.delete(mPath);// 删除完成会返回当前删除的对象
    mEvent.data = deletedEntry;// 数据的赋值
   } catch (VDiskException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    updateEvent(ctx, e, mEvent);
   }
   return null;
  }
 }

 class FileListTask extends BaseTask {

  /**
   * 通过构造方法初始化IDataCallBack
   * @param dataCallBack
   * @param reqCode 
   */
  public FileListTask(IDataCallBack dataCallBack, int reqCode) {
   super(dataCallBack, reqCode);
   mEvent.reqCode = reqCode;// 请求码赋值
  }

  @Override
  protected Void doInBackground(Void... params) {// 子线程
   try {
    Entry metadata = mApi.metadata("/", null, true, false);
    List<Entry> contents = metadata.contents;
    mEvent.data = contents;// 对应的数据赋值
    // 传递数据
    // 请求码-->区分不同的请求-->请求的统一管理
    // 错误码-->区分不同错误信息-->错误的统一管理
   } catch (VDiskException e) {
    e.printStackTrace();
    updateEvent(ctx, e, mEvent);
   }
   return null;
  }

 }

 /*---------------  抽取asynctask的基类 ---------------*/
 abstract class BaseTask extends AsyncTask<Void, Void, Void> {

  IDataCallBack mDataCallBack;
  Event   mEvent;

  /**
   * 通过构造方法初始化IDataCallBack
   * @param dataCallBack
   * @param reqCode 
   */
  public BaseTask(IDataCallBack dataCallBack, int reqCode) {
   super();
   mDataCallBack = dataCallBack;
   mEvent = new Event();
   mEvent.reqCode = reqCode;// 请求码赋值
  }

  @Override
  protected void onPostExecute(Void result) {
   // 需要用接口对象 传递数据
   mDataCallBack.handleServerData(mEvent.reqCode, mEvent.errCode, mEvent.data);
   super.onPostExecute(result);
  }

 }

}



(2)IDataCallBack.java

public interface IDataCallBack {
 // 传递数据
 // 请求码-->区分不同的请求-->请求的统一管理
 // 错误码-->区分不同错误信息-->错误的统一管理
 void handleServerData(int reqCode, int errCode, Object data);
}

(3)Event.java
public class Event {
 public int reqCode;//请求码
 public int errCode;//错误码
 public Object data;//具体数据
}



(4)CloudEngine.getInstance(this).getFileList(this, CloudEngine.REQ_FILE_LIST);

 

12.asytask使用总结(基本使用,版本差异,简单封装)


1.asytask网址:http://blog.csdn.net/liuhe688/article/details/6532519


2.基本使用
 protected void onPreExecute()
 protected abstract Result doInBackground(Params... params)
 protected void onPostExecute(Result result)
 protected void onProgressUpdate(Progress... values)


3.AsyncTask源码分析
 private static final int CORE_POOL_SIZE = 5;        //核心线程数
 private static final int MAXIMUM_POOL_SIZE = 128;   //最大线程数
 private static final int KEEP_ALIVE = 1;            //超时时间,当线程数超过核心线程数时,超过这个时间的空线程就会被销毁,直到线程数等于核心线程 


4.AsyncTask缺陷
* 1.同时只有5个线程去访问网络-->这个是重点
* 2.线程数目超过128,会抛异常-->这个情况其实还好;


5.AsyncTask版本差异
* CORE_POOL_SIZE MAXIMUM_POOL_SIZE KEEP_ALIVE在不同的版本上.值是不一样;
* 1.5前是串行执行的.每次执行1个任务
* 1.6-2.3之前的版本.是并行执行的.每次执行5个任务
* 3.0后提供串行和并行,默认情况是串行

  executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, null);//串行
  executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, null);//并行


6.AsyncTask简单封装
> 实际开发我们会去继承Asynctask
###AsyncTask函数化的封装,AsyncTask函数式的调用

 

13.asynctask函数式调用


1.相当于handle消息机制


2.asynctask函数式调用Demo


(1)AsyncTaskUtils.java

public class AsyncTaskUtils {
 public static <T> void doAsync(final IDataCallBack<T> callBack) {
  new AsyncTask<Void, Void, T>() {

   protected void onPreExecute() {
    callBack.onTaskBefore();
   };

   @Override
   protected T doInBackground(Void... params) {
    // TODO
    return callBack.onTasking(params);
   }

   protected void onPostExecute(T result) {
    callBack.onTaskAfter(result);
   };

  }.execute();
 }
}



(2)IDataCallBack.java----回调的方法

public interface IDataCallBack<T> {
 /**任务执行之前*/
 void onTaskBefore();

 /**任务执行中...*/
 T onTasking(Void... params);

 /**任务执行之后*/
 void onTaskAfter(T result);

}



(3)BaseActivity.java

public class BaseActivity extends Activity {

 public <T> void doAsync(IDataCallBack<T> callBack) {
  AsyncTaskUtils.doAsync(callBack);
 }

}



(4)MainActivity.java----使用

 findViewById(R.id.btn2).setOnClickListener(new OnClickListener() {

   @Override
   public void onClick(View v) {
    MainActivity.this.doAsync(new IDataCallBack<String>() {

     @Override
     public void onTaskBefore() {

     }

     @Override
     public String onTasking(Void... params) {
      String result = "";
      try {
       DefaultHttpClient httpClient = new DefaultHttpClient();
       HttpGet get = new HttpGet("http://www.baidu.com");
       HttpResponse response = httpClient.execute(get);
       if (response.getStatusLine().getStatusCode() == 200) {
        result = EntityUtils.toString(response.getEntity());
       }
      } catch (Exception e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
      }
      return result;
     }

     @Override
     public void onTaskAfter(String result) {
      System.out.println(result);
     }
    });
   }
  });

 }


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

14.接口回调再次理解-----------------------------------另开博客写总结小


1.handler机制+thread


2.怎么理解接口回调-->接口回调就是一个通知机制


3.作用:1.单纯的通知 2.通知+传值


4. 步骤:
(1).定义接口,以及接口方法
(2).定义接口对象
(3).在某一个地方.接口对象调用接口方法
(5).暴露接口对象(构造方法,setter方法)


5.小Demo
(1)Me.java

public class Me {
private Timer mTimer;
/**想睡觉*/


 public void wantSleep() {
  System.out.println("昨晚敲代码敲到4点钟,突然想睡觉...");
 }



 /**开始睡觉*/
 public void startSleep() {
  mTimer = new Timer();
  mTimer.schedule(new TimerTask() {

   @Override
   public void run() {
    System.out.println("开始呼呼大睡.........");
   }
  }, 0, 1000);
 }

 /**停止睡觉*/
 public void stopSleep() {
  if (mTimer != null) {
   mTimer.cancel();
   mTimer = null;
   System.out.println("停止了睡觉");
  }
 }
}



(2)ClassMate.java

public class ClassMate {
 // 2.定义接口对象
 OnTeacherComeListener mOnTeacherComeListener;

 /**
  * 方式1:通过构造方法赋值
  */
 public ClassMate(OnTeacherComeListener onTeacherComeListener) {
  super();
  mOnTeacherComeListener = onTeacherComeListener;
 }

 public ClassMate() {
  super();
 }

 /**模拟老师来了*/
 public void doTeacherCome(String teacherName) {
  // 3.在某一个地方.接口对象调用接口方法-->老师来了的时候
  mOnTeacherComeListener.onTeachCome(teacherName);
 }

 // 4.暴露接口对象(构造方法,setter方法)

 /**
  * 方式2:通过setter赋值
  */
 public void setOnTeacherComeListener(OnTeacherComeListener onTeacherComeListener) {
  mOnTeacherComeListener = onTeacherComeListener;
 }

}



(3)OnTeacherComeListener.java

// 1.定义接口,以及接口方法
public interface OnTeacherComeListener {
 void onTeachCome(String teacherName);
 void onTeachCome();
}



(4)Test

public class Test {
 public static void main(String[] args) {
  final Me me = new Me();

  // 我想睡觉
  me.wantSleep();
  // 找到一个同桌
  ClassMate classMate = new ClassMate();
  System.out.println("我去和同桌协商......");
  // 和他商量好-->如果老师来了.你拍醒我.让我停止睡觉
  classMate.setOnTeacherComeListener(new OnTeacherComeListener() {

   @Override
   public void onTeachCome(String teacherName) {// 通知+传值的效果
    if ("伍老师".equals(teacherName)) {// 回调过程中.有传值的效果
     System.out.println("伍老师不是班主任,我继续睡觉");
    } else if ("李老师".equals(teacherName)) {
     me.stopSleep();//
    }
   }

   @Override
   public void onTeachCome() {// 通知
   }
  });
  // 模拟商量了2s钟
  try {
   Thread.sleep(2000);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
  // 开始睡觉
  me.startSleep();

  // 模拟伍老师来了.
  try {
   Thread.sleep(10000);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }

  classMate.doTeacherCome("伍老师");
  // 模拟伍老师来了.
  try {
   Thread.sleep(10000);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
  classMate.doTeacherCome("李老师");

 }
}




15.自定义异常,统一异常处理

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值