├── Android ├── ActionBar.md ├── Activity.md ├── Broadcast.md ├── ContentProvider与ContentResolver.md ├── Fragment高级使用及问题解决.md ├── Handler.md ├── Loader.md ├── MediaPlayer.md ├── Service.md ├── Timer.md ├── UI_Fragment.md ├── UI_Notification.md ├── UI_Resources.md └── 存储.md ├── Android工具使用 └── ADB.md ├── Android第三方库 ├── picasso.md ├── 推送-极光推送.md ├── 支付及其项目集成.md └── 购物车设计.md ├── File操作.md ├── Home.md ├── IO流.md ├── IO流和文件的相关练习.md ├── SQL.md ├── Socket.md ├── _Footer.md ├── _Sidebar.md ├── android工具包 └── 图片的加载与显示.md ├── handler.png ├── issue ├── 多线程相关.md ├── 获取屏幕相关高度.md ├── 获取视图控件的宽高.md └── 视图焦点问题.md ├── javaBasic1.md ├── javaBasic2.md ├── javaBasic3.md ├── javaBasic4.md ├── javaBasic5.md ├── 常用算法.md ├── 概念区别.md ├── 正则.md ├── 网络 └── htmlStrHandle.md ├── 设计模式.md └── 调用图解.PNG /Android/ActionBar.md: -------------------------------------------------------------------------------- 1 | #ActionBar 2 | ##了解ActionBar 3 | 概念:动作栏或导航控件,Action bar就是替换3.0以前的tittle bar和menu 4 | 5 | **主要功能:** 6 | 1)突出显示一些重要操作(如“注册”、“登录”、“搜索”等),将平时隐藏的选项菜单显示成活动项ActionItem; 7 | 2)在程序中保持统一的页面导航和切换方式。这种基于Tab的导航方式,可以切换多个Fragment; 8 | 3)提供基于下拉的导航菜单; 9 | 4)使用程序logo,作为返回APP的HOME主页面或向上的导航操作。 10 | 11 | ActionBar分成四个区域: 12 | > 可显示APP的icon,也可用其他图标代替。当软件不在最高级页面时,图标左侧会显示一个左箭头,用户可以通过这个箭头向上导航 13 | 14 | app icon 图标区: 15 | > 可显示APP的icon,也可用其他图标代替。当软件不在最高级页面时,图标左侧会显示一个左箭头,用户可以通过这个箭头向上导航 16 | 17 | View Control 视图切换: 18 | > drop-down菜单或tab controls,也可以用来显示非交互的内容,例如app title或更长的品牌信息 19 | 20 | action buttons 动作按钮: 21 | > 这个放最重要的软件功能,放不下的按钮就自动进入Action overflow了 22 | 23 | action overflow 溢出动作项: 24 | > 不常用的操作项目自动进入Action overflow 25 | 26 | ##添加与删除ActionBar 27 | ###添加ActionBar 28 | 从Android3.0(API级别 11)开始 29 | 30 | 31 | 默认的主题是Theme.Hole,Action bar被包含在这个主题中 32 | 当targetSdkVersion或minSdkVersion属性被设置为“11”或更大的数值 33 | 34 | Android 3.0以前使用(需要引入appcompat v7 Support Library) 35 | 把Activity的主题设置为Theme.Holo.NoActionBar就可以了 36 | 37 | 在AndroidManifest.xml清单配置文件中: 38 | 39 | 40 | 删除ActionBar 41 | 42 | 使用Action bar的 hide()方法 43 | 44 | 在onCreate()方法中执行如下代码: 45 | ActionBar actionBar = getActionBar(); 46 | actionBar.hide(); 47 | 48 | ###添加ActionBar动作项 49 | 与添加系统菜单相同,重写onCreateOptionsMenu() 50 | 51 | 通过给元素声明android:showAsAction=”ifRoom”属性 52 | 53 | never : 不将该MenuItem显示在ActionBar上(是默认值) 54 | always : 总是将该MenuItem显示在ActionBar上 55 | ifRoom : 当AcitonBar位置充裕时将该MenuItem显示在ActionBar上 56 | withText : 将该MenuItem显示在ActionBar上,并显示该菜单项的文本 57 | collapseActionView : 将该ActionView折叠成普通菜单项。最低API=14 58 | 59 | 重写onOptionsItemSelected()的回调方法,处理用户选择动作项的操作 60 | 61 | ###分隔操作栏 62 | **仅Android4.0(API 级别 14)或以上的版本** 63 | 64 | 在元素中添加uiOptions=”splitActionBarWhenNarrow”属性设置 65 | 66 | ###启动程序图标导航 67 | 作用:是让APP的LOGO也变成可以点击的导航图标 68 | 69 | ActionBar getActionBar() 获取当前Activity的ActionBar对象 70 | ActionBar.setDisplayHomeAsUpEnabled(true); 设置是否将LOGO图标转成可点击的按钮,并在图标前添加一个向左的箭头 71 | ActionBar.setDisplayShowHomeEnabled(true) 设置是否显示LOGO图标 72 | ActionBar.setHomeButtonEnabled(true) 设置是否将LOGO图标转变成可点击的按钮 73 | 74 | ###ActionView的使用 75 | 作用:可编辑的动作项,如SearchView可以直接在ActionBar上使用 76 | 两种方式添加ActionView 77 | 78 | actionLayout属性,指定一个布局文件 79 | actionViewClass属性,指定个实现CollapsibleActionView的子类 80 | 81 | 手动展开和折叠菜单栏 82 | 83 | MenuItem.expandActionView() 展开ActionView 84 | MenuItem.collapseActionView() 折叠ActionView 85 | MenuItem.setOnActionExpandListener() 设置展开或折叠的监听事件 86 | 87 | ###ActionProvider的使用 88 | 作用:指定动作项的意图,动作项被执行时会列出响应这个意图的所有应用程序 89 | 使用ShareActionProvider类 90 | 91 | 在item里设置android:actionProviderClass="android.widget.ShareActionProvider" 92 | 获取ShareActionProvider对象 93 | 调用setShareIntent()方法 94 | 95 | 注意: 96 | 默认情况,ShareActionProvider对象会基于用户的使用频率来保留共享目标的排列顺序。 97 | 默认情况下,排序信息被保存在由DEFAULT_SHARE_HISTORY_FILE_NAME指定名称的私有文件中。 98 | 如果不同shareActionProvider需要分别保存顺序 99 | 调用setShareHistoryFileName()方法,并且提供一个XML文件的名字(如custom_share_history.xml) 100 | mShareActionProvider.setShareHistoryFileName("custom_share_history.xml"); 101 | 尽管ShareActionProvider类是基于使用频率来排列共享目标的,但是这种行为是可扩展的,并且ShareActionProvider类的扩展能够基于历史文件执行不同的行为和排序。 102 | 103 | 创建一个自定义的动作提供者 104 | 105 | **继承ActionProvider类** 106 | **实现合适的回调方法** 107 | - 重写ActionProvider(Context) 108 | 109 | `这个构造器把应用程序的Context对象传递个操作提供器,你应该把它保存在一个成员变量中,以便其他的回调方法使用。` 110 | 111 | - 重写OnCreateActionView() 创建菜单项的操作视图,并返回View 112 | `这是你给菜单项定义操作视窗的地方。使用从构造器中接收的Context对象,获取一个LayoutInflater对象的实例,并且用XML资源来填充操作视窗,然后注册事件监听器,代码如下`: 113 | 114 | public View onCreateActionView() { 115 | // Inflate the action view to be shown on the action bar. 116 | LayoutInflater layoutInflater = LayoutInflater.from(mContext); 117 | View view = layoutInflater.inflate(R.layout.action_provider, null); 118 | ImageButton button = (ImageButton) view.findViewById(R.id.button); 119 | button.setOnClickListener(new View.OnClickListener() { 120 | @Override 121 | public void onClick(View v) { 122 | // Do something... 123 | } 124 | }); 125 | return view; 126 | } 127 | 128 | - onPerformDefaultAction() 选择上下文菜单项时调用 129 | 130 | 在选中悬浮(上下文)菜单中的菜单时,系统会调用这个方法,并且操作提供器应该这对这个选中的菜单项执行默认的操作。 131 | 132 | - onPrepareSubMenu() 选择子菜单项时调用 133 | 134 | 回调方法来显示子菜单。这样onPerformDefaultAction()在子菜单显示时就不会被调用。 135 | 注意: 实现了onOptionsItemSelected()回调方法的Activity或Frament对象能够通过处理item-selected事件(并且返回true)来覆盖操作提供器的默认行为,这种情况下,系统不会调用onPerformDefaultAction()回调方法。 136 | 137 | **在item里面引用 ** 138 | 139 | android:actionProviderClass="com.example.actionbar.MyActionProvider" 140 | 141 | 142 | ###ActionBarTab的使用 143 | 作用:通常用选项标签使Fragmengt之间相互切换 144 | 使用步骤: 145 | **实现ActionBar.TabListener接口** 146 | 147 | 警告:针对每个回调中的Fragment事务,你都不必调用commit()方法---系统会调用这个方法,并且如果你自己调用了这个方法,有可能会抛出一个异常。你也不能把这些Fragment事务添加到回退堆栈中 148 | 149 | class MyTabListener implements ActionBar.TabListener{ 150 | @Override 151 | public void onTabSelected(Tab tab, FragmentTransaction ft) { 152 | int tag = Integer.parseInt(tab.getTag().toString()); 153 | switch(tag){ 154 | case 1: 155 | ft.replace(R.id.main, new FragmentA(),"fragmentA"); 156 | //ft.addToBackStack("fragmentA");不能加入回退栈 157 | break; 158 | case 2: 159 | ft.replace(R.id.main, new FragmentB(),"fragmentB"); 160 | break; 161 | case 3: 162 | ft.replace(R.id.main, new FragmentC(),"fragmentC"); 163 | break; 164 | } 165 | //ft.commit();不用调用提交方法 166 | } 167 | 168 | @Override 169 | public void onTabUnselected(Tab tab, FragmentTransaction ft) { 170 | // TODO Auto-generated method stub 171 | 172 | } 173 | 174 | @Override 175 | public void onTabReselected(Tab tab, FragmentTransaction ft) { 176 | // TODO Auto-generated method stub 177 | 178 | } 179 | 180 | } 181 | 182 | **必须调用ActionBar.setNavigationMode(NAVIGATION_MODE_TABS)方法让选项标签可见** 183 | 184 | actionBar = getActionBar(); 185 | //设置导航模式 186 | actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); 187 | actionBar.setDisplayShowTitleEnabled(false); 188 | 189 | //如果选项标签的标题实际指示了当前的View对象,你也可以通过调用setDisplayShowTitleEnabled(false)方法来禁用Activity的标题 190 | 191 | **创建ActionBar.Tab选项标签对象并设置监听事件** 192 | 193 | 对于每个要添加的选项标签,都要实例化一个ActionBar.Tab对象,并且调用setTabListener()方法设置ActionBar.Tab对象的事件监听器,还可以用setText()或setIcon()方法来设置选项标签的标题或图标。 194 | 195 | Tab tab1 = actionBar.newTab(); 196 | tab1.setIcon(R.drawable.calendar); 197 | tab1.setTabListener(new MyTabListener()); 198 | tab1.setTag("1"); 199 | 200 | **调用ActionBar.addTab(Tab)方法,将选项标签添加到动作栏中** 201 | 202 | ###添加下拉式导航 203 | 1. 创建一个给Spinner使用的item布局文件 204 | 2. 实现ActionBar.OnNavigationListener回调接口,处理用户选择列表项的事件 205 | 3. 调用ActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST)方法启用导航模式 206 | 4. 用setListNavigationCallbacks()方法给下拉列表设置回调方法 207 | 1. actionBar.setListNavigationCallbacks(mSpinnerAdapter, mNavigationCallback); 208 | 2. 这个方法需要`SpinnerAdapter`和ActionBar.OnNavigationListener对象 209 | 210 | ###ActionBar相关类 211 | 212 | ActionBar Activity.getActionBar() 获取ActionBar对象 213 | hide() 隐藏 214 | show() 显示 215 | setNavigationMode(int mode) 设置导航模式 216 | ActionBar.NAVIGATION_MODE_LIST 下拉列表 217 | NAVIGATION_MODE_STANDARD 默认 218 | NAVIGATION_MODE_TABS 页卡 219 | Tab newTab() 创建页卡 220 | 221 | Menu MenuItem findItem(int id) 查找菜单项或action item 222 | 223 | ###ViewPager 224 | ####ViewPager 225 | 特点:可以左右滑动的控件,需要PagerAdapter配合使用,由v4包提供 226 | 227 | 类全名: android.support.v4.view.ViewPager 228 | 使用步骤 229 | - 在布局文件中使用标签 230 | 231 | 236 | 237 | 可以在ViewPager标签内增加选项卡控件,如 238 | 243 | 244 | 245 | 250 | 251 | 252 | 253 | 258 | 259 | - 代码中增加显示的页面 260 | 261 | LayoutInflater lf = getLayoutInflater().from(this); 262 | 263 | view1 = lf.inflate(R.layout.layout1, null); 264 | view2 = lf.inflate(R.layout.layout2, null); 265 | view3 = lf.inflate(R.layout.layout3, null); 266 | viewList = new ArrayList();// 将要分页显示的View装入数组中 267 | viewList.add(view1); 268 | viewList.add(view2); 269 | viewList.add(view3); 270 | 271 | - 在Activity里实例化ViewPager组件,并设置它的Adapter(即PagerAdapter) 272 | 273 | public class MyViewPagerAdapter extends PagerAdapter{ 274 | private List mListViews; 275 | 276 | public MyViewPagerAdapter(List mListViews) { 277 | this.mListViews = mListViews;//构造方法,参数是我们的页卡,这样比较方便。 278 | } 279 | 280 | @Override 281 | public Object instantiateItem(ViewGroup container, int position) { //这个方法用来实例化页卡 282 | container.addView(mListViews.get(position), 0);//添加页卡 283 | return mListViews.get(position); 284 | } 285 | 286 | @Override 287 | public void destroyItem(ViewGroup container, int position, Object object) { 288 | container.removeView(mListViews.get(position));//删除页卡 289 | } 290 | 291 | @Override 292 | public int getCount() { 293 | return mListViews.size();//返回页卡的数量 294 | } 295 | 296 | @Override 297 | public boolean isViewFromObject(View arg0, Object arg1) { 298 | return arg0==arg1;//判断View是否来源于Object,官方提示写法:return view == object; 299 | } 300 | } 301 | 302 | 简单应用实例 303 | 304 | layout布局文件 305 | 306 | 307 | 311 | 312 | 317 | 318 | 323 | 324 | 325 | 326 | 327 | src代码: 328 | 329 | public class ViewPagerDemo extends Activity { 330 | 331 | private View view1, view2, view3;//需要滑动的页卡 332 | private ViewPager viewPager;//viewpager 333 | private PagerTitleStrip pagerTitleStrip;//viewpager的标题 334 | private PagerTabStrip pagerTabStrip;//一个viewpager的指示器,效果就是一个横的粗的下划线 335 | private List viewList;//把需要滑动的页卡添加到这个list中 336 | private List titleList;//viewpager的标题 337 | private Button weibo_button;//button对象,一会用来进入第二个Viewpager的示例 338 | private Intent intent; 339 | @Override 340 | public void onCreate(Bundle savedInstanceState) { 341 | super.onCreate(savedInstanceState); 342 | setContentView(R.layout.activity_view_pager_demo); 343 | initView(); 344 | } 345 | 346 | private void initView() { 347 | viewPager = (ViewPager) findViewById(R.id.viewpager); 348 | //pagerTitleStrip = (PagerTitleStrip) findViewById(R.id.pagertitle); 349 | pagerTabStrip=(PagerTabStrip) findViewById(R.id.pagertab); 350 | 351 | pagerTabStrip.setTabIndicatorColor(getResources().getColor(R.color.gold)); //设置指示器颜色 352 | pagerTabStrip.setDrawFullUnderline(false); //是否全部显示指示器颜色(暗淡的) 353 | pagerTabStrip.setBackgroundColor(getResources().getColor(R.color.azure)); //设置背景颜色 354 | pagerTabStrip.setTextSpacing(50); //设置标题的字体间隔 355 | 356 | view1 = findViewById(R.layout.layout1); 357 | view2 = findViewById(R.layout.layout2); 358 | view3 = findViewById(R.layout.layout3); 359 | 360 | LayoutInflater lf = getLayoutInflater().from(this); 361 | view1 = lf.inflate(R.layout.layout1, null); 362 | view2 = lf.inflate(R.layout.layout2, null); 363 | view3 = lf.inflate(R.layout.layout3, null); 364 | 365 | viewList = new ArrayList();// 将要分页显示的View装入数组中 366 | viewList.add(view1); 367 | viewList.add(view2); 368 | viewList.add(view3); 369 | 370 | titleList = new ArrayList();// 每个页面的Title数据 371 | titleList.add("wp"); 372 | titleList.add("jy"); 373 | titleList.add("jh"); 374 | 375 | PagerAdapter pagerAdapter = new PagerAdapter() { 376 | 377 | @Override 378 | public boolean isViewFromObject(View arg0, Object arg1) { 379 | 380 | return arg0 == arg1; 381 | } 382 | 383 | @Override 384 | public int getCount() { 385 | 386 | return viewList.size(); 387 | } 388 | 389 | @Override 390 | public void destroyItem(ViewGroup container, int position, 391 | Object object) { 392 | container.removeView(viewList.get(position)); 393 | 394 | } 395 | 396 | @Override 397 | public int getItemPosition(Object object) { 398 | 399 | return super.getItemPosition(object); 400 | } 401 | 402 | @Override 403 | public CharSequence getPageTitle(int position) { 404 | 405 | return titleList.get(position);//指示控件中显示的标题 406 | } 407 | 408 | @Override 409 | public Object instantiateItem(ViewGroup container, int position) { 410 | container.addView(viewList.get(position)); 411 | 412 | weibo_button.setOnClickListener(new OnClickListener() { 413 | 414 | public void onClick(View v) { 415 | intent=new Intent(ViewPagerDemo.this,WeiBoActivity.class); 416 | startActivity(intent); 417 | } 418 | }); 419 | return viewList.get(position); 420 | } 421 | }; 422 | viewPager.setAdapter(pagerAdapter); 423 | } 424 | 425 | @Override 426 | public boolean onCreateOptionsMenu(Menu menu) { 427 | getMenuInflater().inflate(R.menu.activity_view_pager_demo, menu); 428 | return true; 429 | } 430 | 431 | } 432 | 433 | 实现引导界面功能 434 | 435 | -------------------------------------------------------------------------------- /Android/Activity.md: -------------------------------------------------------------------------------- 1 | #Activity 2 | 3 | ##Activity之间传值 4 | 5 | Activity跳转,返回数据/结果 6 | 需要返回数据或结果的,则使用startActivityForResult (Intent intent, int requestCode) 7 | ,requestCode的值是自定义的,用于识别跳转的目标Activity。 8 | 跳转的目标Activity所要做的就是返回数据/结果,setResult(int resultCode)只返回结果不带数据,或者setResult(int resultCode, Intent data)两者都返回! 9 | 而接收返回的数据/结果的处理函数是onActivityResult(int requestCode, int resultCode, Intent data),这里的requestCode就是startActivityForResult的requestCode,resultCode就是setResult里面的resultCode,返回的数据在data里面。 10 | 11 | ###A Activity启动B Activity,并向B传值 12 | 13 | Intent intent = new Intent(A.this,B.class); 14 | //TODO 向intent中放入数据 15 | startActivity(intent) 16 | 17 | ###A 启动 B ,并向B传值,且希望B处理完后回传给A数据 18 | 19 | A中: 20 | 21 | Intent intent = new Intent(A.this,B.class); 22 | //TODO 向intent中放入数据 23 | startActivityForResult (intent, requestCode); 24 | 25 | 然后: 26 | 27 | @Override 28 | protected void onActivityResult(int requestCode, int resultCode, Intent data) { 29 | //在这里做相应判断获取数据 30 | } 31 | 32 | B中: 33 | 34 | 35 | -------------------------------------------------------------------------------- /Android/Broadcast.md: -------------------------------------------------------------------------------- 1 | #Broadcast 广播 四大组件之一 2 | ##接受广播BroadcastReceiver: 3 | 4 | ###使用三要素:频道(Action)、权限、数据字段 5 | 6 | ###定义: 7 | 广播接收器,即接收通过某一频道(Action)发送的广播,发送者可以是Activity和Service 8 | 9 | ###作用: 10 | - 监听系统的广播,并做相应的处理,如电量过低时需要保存相关数据,或发出通知警告用户 11 | - 后台运行的服务,如经过耗时操作后,获取了网络数据,通过广播的方式通知用户 12 | 13 | ###分类: 14 | ####系统广播 15 | 常见的系统广播:**注意:系统广播要严格按照官方API的说明方式使用** 16 | 17 | Intent.ACTION_BOOT_COMPLETED 系统开机启动完成 18 | Intent.ACTION_SHUTDOWN 关机提醒广播 19 | Intent.ACTION_BATTERY_LOW 低电量提醒广播 20 | Intent.ACTION_SCREEN_OFF 屏幕被关闭 21 | Intent.ACTION_SCREEN_ON 屏幕已经被打开 22 | Intent.ACTION_USER_PRESENT 屏幕解锁广播 23 | Intent.ACTION_NEW_OUTGOING_CALL 拨号广播 24 | TelephonyManager.ACTION_PHONE_STATE_CHANGED 来电时电话状态变化广播,如响玲、空置、挂断 25 | Telephony.Sms.Intents.SMS_RECEIVED_ACTION 接收短信的广播 26 | 27 | `Intent.ACTION_BATTERY_CHANGED 电量发生变化广播` **这个仅支持代码中注册** 28 | 29 | ###用法及示例 30 | 1. 创建类,继承`BroadcastReceiver`类 31 | 2. 重写`onReceiver(Context,Intent)`方法 32 | 3. 注册广播(根据需要使用以下两种方式之一就行) 33 | 1. 在`AndroidManifest.xml`中注册(全局) 34 | 2. 动态注册(局部):`registerReceiver(BroadcastReceiver,IntentFilter)` 35 | 4. 发送广播(依需任性其一) 36 | 1. `Context.sendBroadcast(Intent)` 37 | 2. `Context.sendBroadcast(Intent,String)` 带有权限发送广播 38 | 39 | 示例:**开机启动服务** 40 | 41 | 第一步: 42 | public class BootBroadcastReceiver extends BroadcastReceiver { 43 | @Override 44 | public void onReceive(Context context, Intent intent) { 45 | //这里自定义启动你想要启动的服务,获取其他 46 | Intent service = new Intent(context, MyService.class); 47 | context.startService(service); 48 | Log.d("DUBAG", "onReceive 接受到系统开机的广播"); 49 | } 50 | } 51 | 52 | 第二步:配置xml文件,在receiver接收这种添加intent-filter配置 53 | 54 | 55 | 56 | 57 | 58 | 59 | 第三步:添加权限 60 | 61 | ###广播的生命周期 62 | **生命周期方法:** 63 | 64 | public void onCreate() {};//只执行一次,用于初始化Service 65 | public int onStartCommand(Intent intent, int flags, int startId){};//每次启动Service都会执行的方法,在此实现核心的功能 66 | public void onDestroy() {};//只执行一次,用于销毁Service组件 67 | public IBinder onBind(Intent intent) {}; 68 | 69 | **注意:** 70 | 71 | - 广播接收者的生命周期是非常短暂的,在接收到广播的时候创建,`onReceive()`方法结束之后销毁 72 | - 广播接收者中不要做一些耗时的工作,否则会弹出`Application Not Response`错误对话框 73 | - 最好也不要在广播接收者中创建子线程做耗时的工作,因为广播接收者被销毁后进程就成为了空进程,很容易被系统杀掉 74 | - 耗时的较长的工作最好放在服务中完成 75 | 76 | ###有序广播 77 | 78 | 有序广播:是通过Context.sendOrderedBroadcast来发送,所有的receiver依次执行,**有序广播被中断后就不在发送,其他未接受到的接受者将不会接受到** 79 | 80 | Context.sendOrderedBroadcast(Intent,String)//发送有序广播 81 | BroadcastReceiver.abortBroadcast() 中断广播,使级别低的广播接收器不能接收此广播 82 | 声明广播接收级别:android:priority="1000" 83 | 84 | ###粘性广播 85 | 86 | sendStickyBroadcast() 发送粘性的广播 87 | android.Manifest.permission.BROADCAST_STICKY 声明权限 88 | 89 | 特点 90 | 91 | - Intent会一直保留到广播事件结束,没有所谓的10秒限制 92 | - 普通的广播如果onReceive方法执行时间太长,超过10秒的时候系统会将这个广播置为可以干掉的candidate,一旦系统资源不够的时候,就会干掉这个广播而让它不执行 93 | 94 | ###广播的安全性 95 | 发送广播时: 96 | 1. 发送带权限的广播 97 | - `sendBroadcast(Intent,String)` 98 | 2. 指定接收广播的应用包名 99 | - `Intent.setPackage("com.wswenyue.xxx")` 100 | 101 | 在AndroidManifest.xml清单中配置 102 | 103 | 定义权限 104 | 使用权限 105 | 106 | 注册接收广播时: 107 | 108 | Context.registBroadcast(Intent,String),String为接收广播的权限不接收外部应用的广播 109 | 110 | 111 | ###本地广播LocalBroadcastManager: 112 | **如果是在本应用中使用,官方推荐使用本地广播,因为它具有较高的安全性,和普通广播相比有较高的性能及优化** 113 | 114 | 所在包:android.support.v4.content 115 | //获取本地广播管理器 116 | LocalBroadcastManager manager = LocalBroadcastManager.getInstance(Context) 117 | //注册本地广播接受者 118 | manager.registReceiver(BroadcastReceiver,IntentFilter) 119 | //发送本地广播 120 | manager.sendBroadcast(Intent) 121 | //异步发送本地广播 122 | manager.sendBroadcastSync(Intent intent) 123 | //注销本地广播 124 | manager.unregisterReceiver(BroadcastReceiver receiver) 125 | 126 | 127 | ##广播发送很简单 128 | 129 | Intent serviceIntent = new Intent(); 130 | //指定频道Action 131 | serviceIntent.setAction("wenyue.com.service"); 132 | //如果有数据,给Intent加上数据 133 | //发送广播 134 | sendBroadcast(serviceIntent) 135 | 136 | 137 | -------------------------------------------------------------------------------- /Android/ContentProvider与ContentResolver.md: -------------------------------------------------------------------------------- 1 | #ContentProvider(内容提供者)---四大组件之一 2 | **ContentProvider组件的作用**:为外界应用提供本应用中私有数据库中的数据 3 | **ContentResolver的作用**:访问ContentProvider提供的内容 4 | 5 | ##使用ContentResolver访问ContentProvider提供的资源 6 | 1. 获取相应资源的Uri 7 | 8 | 系统提供的Uri有: 9 | 10 | CallLog.Calls.CONTENT_URI;// 11 | 12 | 2. 得到ContentResolver对象,并查询uri代表的资源 13 | 14 | ContentResolver resolver = getContentResolver(); 15 | //查询uri代表的资源(从 Uri代表的表中进行查询) 16 | Cursor cursor = resolver.query(callUri, columns, null, null, null); 17 | //也可以一起写 18 | getContentResolver().query(callUri, columns, null, null, null);//执行相应的指令就行 19 | 20 | 3. 解析获取的Cursor结果集对象 21 | 4. 22 | -------------------------------------------------------------------------------- /Android/Fragment高级使用及问题解决.md: -------------------------------------------------------------------------------- 1 | #fragment相关问题 2 | ##复用 3 | 4 | **实现Fragmnet复用的方法:** 5 | 6 | ```java 7 | private void showFragment(String tag, Class modelFragment, int layoutId) { 8 | Fragment f = fm.findFragmentByTag(tag); 9 | if (f == null) { 10 | //首次显示 11 | try { 12 | f = modelFragment.newInstance(); 13 | } catch (Exception e) { 14 | e.printStackTrace(); 15 | } 16 | 17 | 18 | if (curFragment == null) { 19 | //显示的第一页面 20 | 21 | fm.beginTransaction() 22 | .add(layoutId, f, tag) 23 | .commit(); 24 | } else { 25 | //隐藏当前正显示的Fragment,并增加第一次显示的model1-f 26 | fm.beginTransaction() 27 | .hide(curFragment) 28 | .add(layoutId, f, tag) 29 | .commit(); 30 | } 31 | } else { //之前已显示过了,再次显示 32 | if (curFragment == f) return; 33 | 34 | fm.beginTransaction() 35 | .hide(curFragment) 36 | .show(f) 37 | .commit(); 38 | } 39 | 40 | curFragment = f; 41 | } 42 | ``` -------------------------------------------------------------------------------- /Android/Handler.md: -------------------------------------------------------------------------------- 1 | #Handler 2 | ##总结 3 | ###handler负责发送消息,Looper负责接收Handler发送的消息,并直接把消息回传给Handler自己 4 | ###MessageQueue就是一个存储消息的容器 5 | 6 | ##handler是什么? 7 | - Android中更新UI的一套机制 8 | - 消息处理机制 9 | - 发送,处理消息 10 | 11 | > 所有的Activity的生命周期的回调方法都是通过Handler机制发送相应消息,根据不同的Message做出不同的分支处理。 12 | > AMS(ActivityManageService)发送消息给ActivityThread,然后由ActivityThread对相应消息做出相应方法的回调。 13 | 14 | ##为什么要使用Handler,不使用行吗? 15 | Android在设计的时候就封装了这样一套消息创建,传递,处理机制,如果不遵循这样的规则就没有办法更新UI。就会抛出异常 16 | 17 | ###最根本的原因:为了解决多线程并发的问题 18 | 假如在一个Activity中,有多个线程去更新UI,并且都没有加锁机制,就会产生: 19 | 20 | **更新界面错乱** 21 | 22 | 如果加锁: 23 | 24 | **性能下降** 25 | 26 | 基于以上问题的处理:Android给我们提供了Handler机制,我们只要遵循这样的机制去更新UI就可以,而不用考虑上面的问题。 27 | 28 | 29 | ##Handler的使用 30 | - sendMessage 31 | - sendMessageDelayed 32 | - post(Runnable) 33 | - postDelayed(Runnable) 34 | 35 | ##消息机制处理的原理: 36 | 37 | ###一、Handler:封装了消息的发送(主要包括消息发送给谁) 38 | ###二、Looper 39 | - 内部包含了一个MessageQueue(消息队列),所有的Handler发送的消息都走向这个消息队列 40 | - Looper.looper方法,就是一个死循环,它不断的从MessageQueue中取消息,如果有消息就处理消息,没有消息就阻塞。 41 | 42 | ###三、MessageQueue 就是一个消息队列,可以添加消息,并处理消息 43 | 44 | ###四、Handler,内部会跟Looper进行关联,Handler内部获取到Looper后也就找到了MessageQueue,Handler中发送消息其实就是向这个MessageQueue队列中发送消息 45 | 46 | ###总结: 47 | - handler负责发送消息,Looper负责接收Handler发送的消息,并直接把消息回传给Handler自己 48 | - MessageQueue就是一个存储消息的容器 49 | 50 | ##如何实现一个与线程相关的Handler 51 | Looper.prepare(); 52 | 53 | handler = new Handler() 54 | { 55 | public void handleMessage(android.os.Message msg) 56 | { 57 | //TODO 58 | }; 59 | }; 60 | 61 | Looper.loop(); 62 | 63 | ##更新UI的几种方式: 64 | - runOnUiThread 65 | - handler post 66 | - handler sendMessage 67 | - view post 68 | 69 | ##非Ui线程真的不能更新UI吗 70 | -------------------------------------------------------------------------------- /Android/Loader.md: -------------------------------------------------------------------------------- 1 | #Loader 2 | ##概念及使用 3 | ###概念:用于对数据进行异步加载 4 | 5 | 一、引入: 6 | 由于SimpleCursorAdapter处理大数据时会出现反应慢甚至ANR,故引用Loader,它可以对数据进行异步加载,提升了应用的稳定性。使用Loader时,要求SDK最低版本是11,即Android 3.0 7 | 二、特点: 8 | 1.对每一个Activity或fragment都有效 9 | 2.提供异步加载数据的机制 10 | 3.监视数据源的变化,并针对变化返回一个新的结果 11 | 4.由于配置发生变化而重新被创建后,它们会自动重新连接到上一个加载器的游标,所以不必重新查询数据 12 | 13 | ###使用方法: 14 | #### 使用Loader时包含的组件 15 | 16 | Activity或Fragment 17 | 一个LoaderManager实例,用于管理Loader 18 | 使用CursorLoader,用于查询ContentProvider的数据 19 | 实现LoaderMnager.LoaderCallBacks,它可以初始化一个Loader或者管理Loader 20 | 要想显示Loader的数据,可以使用SimpleCursorAdapter并使用观察者模式 21 | 当使用CursorLoader时,数据源会是一个ContentProvider 22 | 23 | #### 启动Loader 24 | **LoaderManager管理Activity或fragment中的一个或多个Loader** 25 | 26 | **通常在Activity的onCreate()方法中对LoaderManager进行初始化** 27 | 28 | 代码如下: 29 | getLoaderManager().initLoader(0, null, this); 30 | 31 | initLoader()方法中参数说明: 32 | ----------------------------- 33 | 第一个参数: Loader的ID, 34 | 第二个参数: Bundle对象,用于存放数据 35 | 第三个参数: LoaderMnager.LoaderCallBacks回调 36 | 37 | 注意:Loader的ID必须唯一 38 | 39 | **保证一个Loader被初始化并激活,它具有两种可能的结果** 40 | 41 | a.如果初始化的Loader ID已存在,将重用原来的Loader 42 | b.如果初始化的Loader ID不存在,将使用LoaderMnager.LoaderCallBacks中的onCreateLoader()实例化一个Loader对象,它是创建Loader对象的发源地 43 | 44 | #### 重启Loader 45 | **当有新数据更新时,需要使用restartLoader()方法对该Loader进行重启** 46 | 47 | **使用方法: getLoaderManager().restartLoader(0, null, this)** 48 | 49 | ### LoaderManager 50 | 51 | 作用: 管理Loader的启动、重启和注销 52 | 获取LoaderManager对象: Activity.getLoaderMaanager() 53 | initLoader(int id, Bundle args, LoaderCallbacks callback): 初始化和启动一个Loader 54 | restartLoader(int id, Bundle args, LoaderCallbacks callback): 通过loader id重新启动一个Loader 55 | destroyLoader(int id): 注销一个Loader 56 | 57 | ###LoaderMnager.LoaderCallBacks 58 | 59 | 使用LoaderMnager.LoaderCallBacks回调 60 | 61 | ①Loader onCreateLoader(int id,Bundle args):根据传入的ID,初始化并返回一个Loader 62 | 一般在LoaderManager.initLoader()或LoaderManager.restartLoader()时调用 63 | 64 | ②onLoadFinished(Loader loader,D data): 65 | 当上一个Loader完成加载过程之后调用,在该方法中会进行数据的更新,比如adapter.swapCursor(data); 66 | 67 | ③onLoaderReset(Loader loader): 68 | 当一个已创建的Loader重启使其老数据无效时,调用该方法,在该方法中会将数据清空,比如adapter.swapCursor(null); 69 | 70 | ## CursorLoader 71 | 72 | CursorLoader(Context context, Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) 73 | 74 | 方法的参数说明 75 | -------------------------- 76 | context→上下文对象 77 | uri→其他应用所提供的Uri 78 | projection→字段集合 79 | selection →查询条件 80 | selectionArgs →查询条件中包含的参数 81 | sortOrder →排序字段 82 | 83 | **作用:加载ContentProvider提供的数据** 84 | 85 | **父类: AsyncTaskLoader ->Loader** 86 | 87 | **CursorLoader(Context, Uri, String[], String, String[], String)** 88 | 89 | ## AsyncTaskLoader 90 | 父类:android.content.Loader 91 | 92 | 概念: 抽像的Loader子类,并提供AsyncTask类来工作,用于加载大数据 93 | 94 | 主要方法 95 | 96 | onStartLoading() 开始启动Loader方法 97 | 如果AsyncTaskLoader是第一次启动,必须执行 forceLoad()方法 98 | 以下方法不需要重写 99 | D loadInBackground() 后台加载数据的处理方法 100 | deliverResult(D result) 发布数据的处理方法 101 | onContentChanged() 数据内容改变时的处理方法 102 | 103 | 使用方法:同CursorLoader 104 | 105 | ##SearchView 106 | **父类**:LinearLayout 107 | 108 | **概念**:文本搜索控件,可用于ActionBar上的ActionView控件 109 | 110 | **常用属性** 111 | 112 | android:inputType="text" 设置输入内容的类型,同EditText的inputType属性 113 | android:iconifiedByDefault="true" 是否图标化,true为图标化,在点击图标时才显示文本输入框 114 | android:queryHint 设置提示文本信息 115 | 116 | **设置查询文本事件监听器**:setOnQueryTextListener(SearchView.OnQueryTextListener) 117 | 118 | onQueryTextChange(String newText) 查询内容发生改变时 119 | onQueryTextSubmit(String query) 按“Enter“或"Search"键提交查询内容 -------------------------------------------------------------------------------- /Android/MediaPlayer.md: -------------------------------------------------------------------------------- 1 | #MediaPlayer 2 | 使用MediaPlayer播放音频、视频文件要遵循Google官方给出的MediaPlayer状态图,来调用。 3 | ##状态图 4 | 状态图定义了在某个状态以该干什么,或者能做什么,如果不按照状态图操作,会报出状态调用异常 5 | 6 | ![mediaplayer_state_diagram](http://7xj2yt.com1.z0.glb.clouddn.com/android_mediaplayer_state_diagram.gif) 7 | 8 | -------- 9 | 10 | ##方法及使用 11 | ###创建MediaPlayer可以使用静态方法create 12 | 13 | static MediaPlayer create(Context context, int resid) 14 | static MediaPlayer create(Context context, Uri uri) 15 | 16 | 使用该方法创建成功后就进入了`prepare`的状态 17 | 18 | ###常用方法 19 | 20 | setDataSource(String path) 设置媒体源 21 | setLooping(boolean) 设置是否循环播放 22 | prepare() 预处理,调用start()前必须先调用此方法 23 | start() 开始播放 24 | pause()暂停播放 25 | stop() 停止播放 26 | isPlaying() 是否正在播放 27 | reset() 重置播放器,进入idle空闲状态 28 | release() 释放资源 29 | getDuration() 获取播放文件的总时长,单位:毫秒 30 | getCurrentPosition() 获取当前播放的位置 31 | seekTo(int position) 定位到指定的播放时间 32 | 33 | 使用示例: 34 | 35 | /** 36 | *MediaPlayer属于长生命周期的类,所以一般使用Service管理: 37 | * 用于管理MediaPlayer的服务组件 38 | */ 39 | public class PlayerService extends Service { 40 | 41 | private MediaPlayer mPlayer; // 媒体文件的播放组件 42 | 43 | private int sumLen; // 总时长 44 | 45 | private LocalBroadcastManager lbMgr;// 本地广播管理器 46 | 47 | private SeektoReceiver seekReceiver; 48 | @Override 49 | public void onCreate() { 50 | // 初始化Service组件 51 | super.onCreate(); 52 | 53 | // 实例化MediaPlayer 54 | mPlayer = MediaPlayer.create(getApplicationContext(), R.raw.ghsy); 55 | 56 | // 获取本地广播管理器对象 57 | lbMgr = LocalBroadcastManager.getInstance(getApplicationContext()); 58 | 59 | seekReceiver=new SeektoReceiver(); 60 | lbMgr.registerReceiver(seekReceiver, new IntentFilter(Config.ACTION_SEEKTO)); 61 | 62 | } 63 | 64 | @Override 65 | public int onStartCommand(Intent intent, int flags, int startId) { 66 | //判断当前意图是否改变播放新的音频文件 67 | if(intent.getBooleanExtra(Config.EXTRA_CHANGE, false)){ 68 | mPlayer.reset();//重置播放器,进入idle空闲状态 69 | try { 70 | //设置新的数据源(新的音频文件),进入initial初始化状态 71 | mPlayer.setDataSource(intent.getStringExtra(Config.EXTRA_PATH)); 72 | 73 | mPlayer.prepare();//进入就绪状态(Prepared) 74 | 75 | } catch (Exception e) { 76 | e.printStackTrace(); 77 | } 78 | } 79 | 80 | 81 | // 判断当前的MediaPlayer是否正在播放 82 | if (mPlayer.isPlaying()) { 83 | mPlayer.pause(); // 暂停 84 | } else { 85 | mPlayer.start(); // 播放 86 | 87 | new ProgressThread().start();// 启动计算播放进度的线程 88 | } 89 | 90 | return super.onStartCommand(intent, flags, startId); 91 | } 92 | 93 | @Override 94 | public void onDestroy() { 95 | super.onDestroy(); 96 | 97 | // 停止播放 98 | mPlayer.stop(); 99 | mPlayer.release();// 释放资源 100 | 101 | lbMgr.unregisterReceiver(seekReceiver); //注销广播接收器 102 | } 103 | 104 | @Override 105 | public IBinder onBind(Intent intent) { 106 | return null; 107 | } 108 | 109 | /** 110 | * 定义计算播放进度的线程类 111 | * 112 | * @author apple 113 | * 114 | */ 115 | class ProgressThread extends Thread { 116 | @Override 117 | public void run() { 118 | 119 | try { 120 | while (mPlayer != null && mPlayer.isPlaying()) { 121 | 122 | sumLen = mPlayer.getDuration();// 获取播放文件的总时长,单位:毫秒 123 | int currentPosition = mPlayer.getCurrentPosition(); // 获取当前播放的位置 124 | 125 | // 准备发送进度广播 126 | Intent intent = new Intent(Config.ACTION_PROGRESS); 127 | intent.putExtra(Config.EXTRA_PROGREES_MAX, sumLen); // 总时长 128 | intent.putExtra(Config.EXTRA_PROGREES_CUR, currentPosition);// 当前进度 129 | 130 | lbMgr.sendBroadcast(intent);// 发送播放的进度广播 131 | 132 | Thread.sleep(200); 133 | 134 | } 135 | 136 | } catch (Exception e) { 137 | e.printStackTrace(); 138 | } 139 | } 140 | } 141 | 142 | class SeektoReceiver extends BroadcastReceiver{ 143 | @Override 144 | public void onReceive(Context context, Intent intent) { 145 | // TODO Auto-generated method stub 146 | int seekPosition=intent.getIntExtra(Config.EXTRA_PROGREES_CUR, 0); 147 | 148 | mPlayer.seekTo(seekPosition);//设置播放器的播放位置 149 | } 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /Android/Service.md: -------------------------------------------------------------------------------- 1 | #Service 2 | 主要内容: 3 | - BindService 绑定服务 4 | - IntentService 带有子线程的服务组件,其内部使用了单线程池模式 5 | - AIDL 进程间(应用间)通信【方法调用、接口】 6 | - 粘性Service【流氓服务,关不掉的服务】 7 | 8 | ##BindService 绑定服务 9 | BindService用于短生命周期的服务,BindService和Activity进行绑定后,其生命周期和Activity的生命周期一致,当Activity销毁了BindService也就销毁了。 10 | 11 | ###bindService方式启动服务组件的生命周期方法 12 | 13 | onCreate() 14 | IBinder onBind(Intent)//返回实例化Binder类的子类 15 | onUnbind() 16 | onDestroy() 17 | 18 | ###bindService的过程 19 | - **在Service组件中,声明Binder类的子类(公共),在其子类中声明组件之间的接口方法** 20 | 21 | - **在onBind()方法中,实例化Binder子类的对象,并返回** 22 | 23 | 24 | - ** 在绑定服务组件端(Activity),实例化ServiceConnection接口对象,并在此接口的onServiceConnected()方法中,将方法的第二个参数IBinder对象强转成Binder子类对象** 25 | 26 | 27 | - **在适当的位置 调用 Context.bindService()来绑定服务。** 28 | 29 | 示例(一个管理定时器的服务组件): 30 | 31 | public class TimerService extends Service { 32 | 33 | private Timer timer; //定时器 34 | 35 | private NotificationManager notifyMgr; 36 | @Override 37 | public void onCreate() { 38 | super.onCreate(); 39 | Log.i("debug", "--onCreate--"); 40 | 41 | timer=new Timer(); 42 | 43 | notifyMgr=(NotificationManager) getSystemService(NOTIFICATION_SERVICE); 44 | } 45 | 46 | @Override 47 | public IBinder onBind(Intent intent) { 48 | Log.i("debug", "--onBind--"); 49 | return new TimerBinder();//2. 实例化Binder的子类,并返回 50 | } 51 | 52 | @Override 53 | public boolean onUnbind(Intent intent) { 54 | Log.i("debug", "--onUnbind--"); 55 | return super.onUnbind(intent); 56 | } 57 | 58 | @Override 59 | public void onDestroy() { 60 | Log.i("debug", "--onDestroy--"); 61 | super.onDestroy(); 62 | } 63 | 64 | //1. 声明Binder类的子类,用于Service与绑定的Activity的组件进行通信 65 | public class TimerBinder extends Binder{ 66 | public void start(){ 67 | Log.i("debug", "----start---"); 68 | 69 | //通过定时器,来安排时间计划 70 | timer.schedule(new TimerTask(){ 71 | @Override 72 | public void run() { 73 | // TODO 在指定的时间执行的任务 74 | 75 | NotificationCompat.Builder builder= 76 | new NotificationCompat.Builder(getApplicationContext()); 77 | builder.setSmallIcon(android.R.drawable.ic_menu_today) 78 | .setContentTitle("提醒") 79 | .setContentText("时间了,该起床了....") 80 | .setTicker("时间了,该起床了....") 81 | .setDefaults(Notification.DEFAULT_SOUND) 82 | .setOngoing(true); 83 | 84 | notifyMgr.notify(2, builder.build()); 85 | 86 | } 87 | },10*1000, 5*1000); 88 | 89 | } 90 | 91 | public void stop(){ 92 | Log.i("debug", "----stop---"); 93 | //关闭所有的定时任务 94 | timer.cancel(); 95 | 96 | notifyMgr.cancel(2); 97 | } 98 | } 99 | 100 | } 101 | 102 | 103 | 绑定服务组件端(Activity),实例化ServiceConnection接口对象 104 | 在ServiceConnection接口对象的onServiceConnected()方法中,将方法的第二个参数IBinder对象强转成Binder子类对象 105 | 106 | 在Activity中绑定服务示例: 107 | 108 | public class MainActivity extends Activity { 109 | 110 | //声明Binder子类对象 111 | TimerBinder timerBinder; 112 | 113 | //3. 实例化ServiceConnection接口(绑定服务组件时使用的回调接口) 114 | ServiceConnection conn=new ServiceConnection(){ 115 | @Override 116 | public void onServiceConnected(ComponentName name, IBinder service) { 117 | // TODO 绑定成功的方法 118 | timerBinder=(TimerBinder) service; 119 | } 120 | 121 | @Override 122 | public void onServiceDisconnected(ComponentName name) { 123 | // TODO 与绑定服务组件断开连接(发生的时机:由于系统原因造成了服务组件停止或销毁) 124 | timerBinder=null; 125 | } 126 | }; 127 | 128 | @Override 129 | protected void onCreate(Bundle savedInstanceState) { 130 | super.onCreate(savedInstanceState); 131 | setContentView(R.layout.activity_main); 132 | } 133 | 134 | public void bindService(View v) { 135 | //绑定服务组件 136 | bindService(new Intent(getApplicationContext(),TimerService.class), 137 | conn, BIND_AUTO_CREATE); 138 | 139 | //BIND_AUTO_CREATE标识表示:绑定的服务组件如果不存,则会自动创建, 140 | //注:由bindService方式启动的Service,其生命周期会受到绑定组件的影响,即当绑定组件Activity销毁时,Service也会停止 141 | } 142 | 143 | public void unbindService(View v) { 144 | unbindService(conn); //解除绑定 145 | } 146 | 147 | public void startTime(View v) { 148 | if(timerBinder!=null){ 149 | timerBinder.start(); 150 | } 151 | } 152 | 153 | public void stopTime(View v) { 154 | if(timerBinder!=null){ 155 | timerBinder.stop(); 156 | } 157 | } 158 | 159 | } 160 | 161 | ###绑定类型 162 | 163 | 绑定服务的类型: 164 | 165 | BIND_AUTO_CREATE 166 | 绑定的service不存在时,会自动创建 167 | BIND_ADJUST_WITH_ACTIVITY 168 | service的优先级别与根据所绑定的Activity的重要程度有关,Activity处于前台,service的级别高 169 | BIND_NOT_FOREGROUND 170 | Service永远不拥有运行前台的优先级 171 | BIND_WAIVE_PRIORITY 172 | Service的优先级不会改变 173 | BIND_IMPORTANT | BIND_ABOVE_CLIENT 174 | 所绑定的Activity处于前台时,Service也处于前台 175 | BIND_ABOVE_CLIENT 指定内存很低的情况下,运行时在终止绑定的Service之前终止Activity 176 | 177 | ##IntentService 178 | 179 | **IntentService是带有子线程的服务组件,其内部使用了单线程池模式,当所有的任务执行完成后,会自动关闭本服务(如果没有任务,大概2秒左右关闭)。** 180 | 181 | ###生命周期方法 182 | 183 | onCreate() //该方法只在创建IntentService时执行,只执行一次 184 | onStartCommand() //每次启动都执行 185 | onHandleIntent() // 在子线程中执行的方法,所有的任务都按照顺序依次执行 186 | onDestroy() 187 | 188 | 一个执行下载任务的示例: 189 | 190 | public class DownloadService extends IntentService { 191 | public DownloadService(){ 192 | super(null);//参数:是设置子线程的名称 193 | } 194 | 195 | @Override 196 | public void onCreate() { 197 | super.onCreate(); 198 | Log.i("debug", "--onCreate---"); 199 | } 200 | @Override 201 | public int onStartCommand(Intent intent, int flags, int startId) { 202 | Log.i("debug", "--onStartCommand---"); 203 | return super.onStartCommand(intent, flags, startId); 204 | } 205 | 206 | @Override 207 | protected void onHandleIntent(Intent intent) { 208 | // TODO 在子线程中执行的方法 209 | Log.i("debug", "--onHandleIntent---"); 210 | //获取下载图片的地址 211 | String path=intent.getStringExtra("path"); 212 | try{ 213 | URL url=new URL(path); 214 | HttpURLConnection conn=(HttpURLConnection) url.openConnection(); 215 | InputStream is=conn.getInputStream(); 216 | byte[] buffer=new byte[10*1024];//每次读取字节的最大数 217 | int len=-1; 218 | 219 | ByteArrayOutputStream baos=new ByteArrayOutputStream(); 220 | if(conn.getResponseCode()==200){ 221 | while((len=is.read(buffer))!=-1){ 222 | baos.write(buffer, 0, len); 223 | } 224 | 225 | byte[] bytes=baos.toByteArray(); 226 | //将下载完成的字节数组转成图片对象 227 | Bitmap bitmap=BitmapFactory.decodeByteArray(bytes, 0, bytes.length); 228 | 229 | //将图片对象发送给Activity进行显示 230 | Intent bitmapIntent=new Intent(Config.ACTION_DOWNLOAD_COMPLETED); 231 | bitmapIntent.putExtra(Config.EXTRA_BITMAP,bitmap); 232 | bitmapIntent.putExtra(Config.EXTRA_URL, path); 233 | 234 | sendBroadcast(bitmapIntent); 235 | 236 | } 237 | 238 | }catch(Exception e){ 239 | e.printStackTrace(); 240 | } 241 | 242 | } 243 | 244 | @Override 245 | public void onDestroy() { 246 | super.onDestroy(); 247 | Log.i("debug", "--onDestroy---"); 248 | } 249 | } 250 | 251 | Activity端调用下载服务【广播接收之类省略】: 252 | 253 | public void startDownload(View view){ 254 | Intent intent=new Intent(getApplicationContext(),DownloadService.class); 255 | intent.putExtra("path", Config.URL1); 256 | startService(intent); //下载第一个图片 257 | 258 | intent.putExtra("path", Config.URL2); 259 | startService(intent); //下载第二个图片 260 | 261 | intent.putExtra("path", Config.URL3); 262 | startService(intent); //下载第三个图片 263 | 264 | } 265 | 266 | 267 | ##AIDL实现跨进程服务 268 | 269 | ###AIDL用于实现进程之间通信[调用服务]的接口 270 | 271 | ###使用方法及步骤: 272 | #### 服务端 273 | 274 | **1. 声明.aidl文件,在此文件中声明进程间的通信接口(类似于Binder子类的作用)** 275 | 276 | 示例: 277 | 278 | ```java 279 | package com.wenyue.aidl; 280 | 281 | interface IRemoteService{ 282 | 283 | void print(String msg); 284 | 285 | String getName(); 286 | } 287 | ``` 288 | 289 | **2.在Service组件的onBind()方法中,返回aidl接口的Stub对象** 290 | 示例: 291 | 292 | ```java 293 | public class RemoteSerice extends Service { 294 | 295 | //2.1 实例化.aidl接口的Stub对象 296 | private IRemoteService.Stub stub=new IRemoteService.Stub() { 297 | 298 | @Override 299 | public void print(String msg) throws RemoteException { 300 | Log.i("debug", "--RemoteSerice---"+msg); 301 | } 302 | 303 | @Override 304 | public String getName() throws RemoteException { 305 | return "RemoteSerice"; 306 | } 307 | }; 308 | 309 | @Override 310 | public IBinder onBind(Intent intent) { 311 | return stub;//2.2 返回aidl接口的Stub对象 312 | } 313 | } 314 | 315 | ``` 316 | 317 | **3. 注册Service组件是,必须要提供一个启动或绑定此组件的Action** 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | ####客户端 328 | 329 | **1.将服务端提供的.aidl文件复制到src下** 330 | 331 | **2.在Activity类中,实例化ServiceConnection接口对象,实现两个回调方法,在onServiceConnected()方法中将第二个参数转化.aidl接口对象** 332 | 333 | **3.在适当的位置调用Context.bindService()方法,进行绑定。此方法的第一个参数:Intent意图,在实例化时,需要指定Service组件的Action** 334 | 335 | 客户端使用示例: 336 | 337 | public class MainActivity extends Activity { 338 | 339 | //声明aild接口对象 340 | IRemoteService remoteService; 341 | 342 | //实例化绑定组件之间的通信接口 343 | ServiceConnection conn=new ServiceConnection() { 344 | 345 | @Override 346 | public void onServiceDisconnected(ComponentName name) { 347 | // TODO Auto-generated method stub 348 | 349 | } 350 | 351 | @Override 352 | public void onServiceConnected(ComponentName name, IBinder service) { 353 | //将第二个参数转化为.aidl接口对象 354 | remoteService=IRemoteService.Stub.asInterface(service); 355 | } 356 | }; 357 | 358 | @Override 359 | protected void onCreate(Bundle savedInstanceState) { 360 | super.onCreate(savedInstanceState); 361 | setContentView(R.layout.activity_main); 362 | 363 | //绑定其它应用的Service组件,在绑定成功之后,将返回的Stub对象转化为aidl接口对象 364 | bindService(new Intent("com.qf.serivce04_aidl_server.RemoteSerice"), 365 | conn, BIND_AUTO_CREATE); 366 | 367 | } 368 | 369 | 370 | public void getRemoteName(View v) throws RemoteException{ 371 | if(remoteService!=null){ 372 | setTitle(remoteService.getName()); 373 | } 374 | } 375 | 376 | 377 | public void print(View v) throws RemoteException{ 378 | if(remoteService!=null){ 379 | remoteService.print("hello,service!!!"); 380 | } 381 | } 382 | } 383 | 384 | ##粘性Service 385 | 和普通的Service一样只是在onStartCommand方法中返回Service.START_STICKY **粘性Service标识**即可 386 | 387 | @Override 388 | public int onStartCommand(Intent intent, int flags, int startId) { 389 | return Service.START_STICKY;//粘性Service标识,当Service组件在非意愿时被停止后,有机率重启 390 | } 391 | 392 | ###关不掉的服务 393 | 思想:开启一个线程在线程run方法里,死循环执行查看服务是否在运行,如果服务死掉,重启服务。 394 | 395 | //查找当前组件的线程,如果当前正运行的服务组件不包含PushService组件时,则启动 396 | class SeekServiceThread extends Thread{ 397 | 398 | @Override 399 | public void run() { 400 | 401 | while(true){ 402 | 403 | //1.获取Activity组件管理器(管理当前应用的进程、服务组件、任务或回退栈) 404 | ActivityManager mgr=(ActivityManager) getSystemService(ACTIVITY_SERVICE); 405 | 406 | //2. 获取正运行的服务组件 407 | List rServices = mgr.getRunningServices(100); 408 | 409 | boolean isFinded=false;//标识是否查找到当前的service组件 410 | for(RunningServiceInfo rService:rServices){ 411 | if(rService.getClass().getName().equals(PushService.class.getName())){ 412 | isFinded=true; 413 | } 414 | } 415 | 416 | if(!isFinded){ //如果没有查找到,则启动本服务组件 417 | 418 | startService(new Intent(getApplicationContext(),PushService.class)); 419 | } 420 | 421 | try { 422 | Thread.sleep(2000); 423 | } catch (InterruptedException e) { 424 | e.printStackTrace(); 425 | } 426 | } 427 | 428 | } 429 | } 430 | 431 | 432 | **注:当然最好的做法是开启两个服务互相查找,如果一方死了,另一方则重启它,利用之间的时间差就行** -------------------------------------------------------------------------------- /Android/Timer.md: -------------------------------------------------------------------------------- 1 | #Timer定时器 2 | 主要使用方法: 3 | 4 | schedule(TimerTask task, Date when) 按排任务在指定时间执行 5 | schedule(TimerTask task, long delay) 按排任务延迟多少毫秒之后执行 6 | schedule(TimerTask task, long delay, long period) 按排任务在延迟多个毫秒后执行,并间隔多少毫秒后重复 7 | cancel() 取消定时器 8 | TimerTask 定时任务 9 | 10 | 示例: 11 | 12 | timer.schedule(new TimerTask(){ 13 | @Override 14 | public void run() { 15 | // TODO 在指定的时间执行的任务 16 | 17 | NotificationCompat.Builder builder= 18 | new NotificationCompat.Builder(getApplicationContext()); 19 | builder.setSmallIcon(android.R.drawable.ic_menu_today) 20 | .setContentTitle("提醒") 21 | .setContentText("时间了,该起床了....") 22 | .setTicker("时间了,该起床了....") 23 | .setDefaults(Notification.DEFAULT_SOUND) 24 | .setOngoing(true); 25 | 26 | notifyMgr.notify(2, builder.build()); 27 | } 28 | },10*1000, 5*1000); -------------------------------------------------------------------------------- /Android/UI_Fragment.md: -------------------------------------------------------------------------------- 1 | #Fragment 2 | ##特点及用途 3 | 4 | - 利用碎片化来解决Android屏幕尺寸差距带来的适配问题 5 | - Fragment拥有自己的生命周期和能接收、处理用户的事件 6 | - 你可以把Fragment当成Activity的一个界面的一个组成部分 7 | - 你可以动态的添加、替换和移除某个Fragment 8 | 9 | ##Fragment的生命周期 10 | Fragment必须是依存与Activity而存在的,因此Activity的生命周期会直接影响到Fragment的生命周期。官网这张图很好的说明了两者生命周期的关系: 11 | 12 | ![Fragment的生命周期](http://7xj2yt.com1.z0.glb.clouddn.com/android_Fragment的生命周期.png) 13 | 14 | 可以看到Fragment比Activity多了几个额外的生命周期回调方法: 15 | onAttach(Activity) 16 | 当Fragment与Activity发生关联时调用。 17 | onCreateView(LayoutInflater, ViewGroup,Bundle) 18 | 创建该Fragment的视图 19 | onActivityCreated(Bundle) 20 | 当Activity的onCreate方法返回时调用 21 | onDestoryView() 22 | 与onCreateView想对应,当该Fragment的视图被移除时调用 23 | onDetach() 24 | 与onAttach相对应,当Fragment与Activity关联被取消时调用 25 | 注意:除了onCreateView,其他的所有方法如果你重写了,必须调用父类对于该方法的实现, 26 | 27 | ##使用Fragment 28 | ###静态使用 29 | -------------------------------------------------------------------------------- /Android/UI_Notification.md: -------------------------------------------------------------------------------- 1 | ##通知 2 | ###示例: 3 | 示例1: 4 | 5 | //创建通知 的构建器对象 6 | NotificationCompat.Builder builder = new NotificationCompat.Builder(this); 7 | 8 | //设置通知的相关属性 9 | builder.setContentTitle("通知"); 10 | 11 | builder.setContentText("下雨了"); 12 | 13 | //必须设置,否则程序会崩溃 14 | builder.setSmallIcon(R.drawable.ic_launcher); 15 | 16 | //得到通知管理对象---属于系统服务 17 | NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 18 | 19 | //得到通知对象 20 | Notification notification = builder.build(); 21 | 22 | //使用通知管理对象发送通知 23 | manager.notify((int)System.currentTimeMillis(), notification);//如果id相同,即使发送多个通知,也只显示一个 24 | 25 | 示例2: 26 | 27 | NotificationCompat.Builder builder = new NotificationCompat.Builder(this); 28 | builder.setContentTitle("你有短信"); 29 | builder.setContentText("你有3条短信"); 30 | builder.setSmallIcon(R.drawable.ic_launcher); 31 | builder.setNumber(3);//设置数量 32 | //收到通知可以 是声音,灯光,震动 33 | //DEFAULT_VIBRATE 需要权限 34 | builder.setDefaults(Notification.DEFAULT_VIBRATE); 35 | 36 | Notification notification = builder.build(); 37 | 38 | NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 39 | 40 | manager.notify(168, notification); 41 | 42 | 示例3: 43 | 44 | NotificationCompat.Builder builder = new NotificationCompat.Builder(this); 45 | builder.setContentTitle("下载"); 46 | builder.setContentText("正在下载"); 47 | builder.setSmallIcon(R.drawable.ic_launcher); 48 | builder.setOngoing(true);//设置不可以被删除 49 | 50 | 51 | Notification n = builder.build(); 52 | 53 | NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 54 | 55 | manager.notify(188, n); 56 | 57 | 示例4: 58 | 59 | NotificationCompat.Builder builder = new NotificationCompat.Builder(this); 60 | 61 | builder.setContentTitle("你有短信") 62 | .setContentText("你有6条短信") 63 | .setSmallIcon(R.drawable.ic_launcher) 64 | .setNumber(6) 65 | .setDefaults(Notification.DEFAULT_ALL); 66 | 67 | Intent intent = new Intent(this,MainActivity.class); 68 | 69 | //可以当通知被点击时自动执行 startActiivty() 70 | PendingIntent pending = PendingIntent.getActivity(this, 6, intent, PendingIntent.FLAG_CANCEL_CURRENT); 71 | 72 | builder.setContentIntent(pending); 73 | 74 | builder.setAutoCancel(true);//设置通知自动消失 75 | 76 | Notification ntf = builder.build(); 77 | 78 | NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 79 | 80 | manager.notify(88, ntf); 81 | 82 | ##Toast自定义 83 | 84 | Toast toast = new Toast(this); 85 | 86 | View view = getLayoutInflater().inflate(R.layout.toast_layout, null); 87 | 88 | toast.setView(view);//设置吐司使用的布局 89 | 90 | toast.setGravity(Gravity.CENTER, 0,0);//设置吐司的显示位置 91 | 92 | toast.setDuration(Toast.LENGTH_SHORT); 93 | 94 | toast.show(); -------------------------------------------------------------------------------- /Android/UI_Resources.md: -------------------------------------------------------------------------------- 1 | #UI资源 2 | ##color资源: 3 | 使用方法: 4 | ###drawable的color资源 5 | 6 | 1、 在drawable目录下创建.xml文件,根标签为 7 | 2、在标签中使用其android:color属性设置颜色值(如:#RGB或@color/xxx) 8 | 3、一般作为背景使用,引用方式:@drawable/xxx 9 | 10 | ###values的color常量 11 | 在values目录下创建`colors.xml`文件 12 | 在``标签中定义颜色: 13 | 14 | 15 | #ffffff 16 | #fffff0 17 | 18 | 19 | **引用方式**:`@color/xxx` 20 | 例如: 21 | 设置字体的颜色 22 | 23 | android:textColor="@color/white" 24 | 25 | 设置布局的背景颜色 26 | 27 | android:background="@color/white" 28 | 29 | ##selector背景选择器 30 | 作用:根据UI控件的不同状态选择相应的颜色资源作为控件的背景 31 | 32 | 常见状态: 33 | 34 | android:drawable 默认 35 | android:state_window_focused="false|true" UI所在窗口是否获得焦点的状态 36 | android:state_focused="false|true" 是否获得焦点,一般与按下状态组件使用 37 | android:state_checked="false|true" 是否勾选的状态 38 | android:state_selected="false|true" 是否选择的状态 39 | android:state_pressed="false|true" 点击或按下的状态 40 | android:state_enabled=“false|true“ 是设置是否响应事件,指所有事件 41 | 42 | 示例: 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 58 | 59 | 60 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 用法: 72 | 73 | 1、 在drawable目录下创建.xml文件,根标签为 74 | 2、 增加标签,并设置不同状态和对应的资源 75 | 3、在UI控件的background属性引用,属性值:@drawable/xx 76 | 77 | 78 | ##shape图形资源 79 | **作用:** `XML` 中定义的几何形状 80 | **位置:** `res/drawable/xxx.xml` 81 | 82 | **根标签** `` 中的 `android:shape属性值` 83 | 84 | rectangle 矩形 85 | oval 椭圆 86 | line 水平直线 87 | ring 环形 88 | 89 | `` 渐变子标签 90 | 91 | android:startColor 起始颜色 92 | android:centerColor 中间颜色 93 | android:endColor 结束颜色 94 | android:angle 渐变角度,0从左到右,90表示从下到上,数值为45的整数倍数,默认为0 95 | android:type 渐变的样式 liner线性渐变 radial环形渐变 sweep 扫视渐变 96 | 97 | `` 填充颜色子标签 98 | 99 | android:color 填充的颜色 100 | 101 | `` 描边子标签 102 | 103 | android:width 描边的宽度 104 | android:color 描边的颜色 105 | android:dashWidth 表示'-' 破折号的宽度 106 | android:dashGap 表示'-' 破折号之间的距离 107 | 108 | `` 圆角子标签 109 | 110 | android:radius 圆角的半径 值越大角越圆 111 | android:topRightRadius 右上圆角半径 112 | android:bottomLeftRadius 右下圆角角半径 113 | android:topLeftRadius 左上圆角半径 114 | android:bottomRightRadius 左下圆角半径 115 | 116 | ``内边距子标签 117 | 118 | android:bottom 底部填充 119 | android:left 左边填充 120 | android:right 右边填充 121 | android:top 上面填充 122 | 123 | 圆角按钮示例: 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | ##layer-list 图层资源 153 | ###作用: 将多个图片或图形按层关系排放,类似帧布局 154 | ###用法同selector,不过根标签为,必须指定id和drawable属性 155 | 156 | 实例:水平进度条: 157 | 158 | ---必须提供一套进度图片(三张)--- 159 | 160 | 161 | ---图层资源文件--- 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | ----布局文件---- 178 | 186 | 187 | ##bitmap资源 188 | ###作用:防止小图片作为背景使用时被拉伸 189 | ###位置:`/res/drawable/*.xml`,根标签为`bitmap` 190 | ###常用属性 191 | 192 | ####src 图片资源位置 193 | ####tileMode 平铺模式 194 | 195 | disabled 不平铺,显示原大小 196 | clamp 固定的重复边缘颜色 197 | repeat 重复(双向平铺) 198 | mirror 反射平铺(镜面映照) 199 | 200 | ####gravity 原大小显示时的对齐方式 201 | 202 | ####antialias 是否抗锯齿 203 | 204 | ##大小(Size)资源 205 | 在values文件下新建dimens.xml文件 206 | 内容格式如下: 207 | 208 | 209 | 210 | 211 | 16dp 212 | 16dp 213 | 214 | 215 | 216 | 20sp 217 | 15sp 218 | 30sp 219 | 220 | 10dp 221 | 222 | 223 | 224 | 225 | ##ID资源 226 | 在values文件下新建ids.xml文件 227 | 内容格式如下: 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | ##style样式 250 | ###作用:android中的样式和CSS样式作用相似,都是用于为界面元素定义显示风格,其包含一个或者多个view控件属性的集合。如:需要定义字体的颜色和大小 251 | ###位置:res/values/styles.xml 252 | ###定义样式: 253 | 254 | 255 | 256 | 262 | 263 | 264 | 265 | --参考系统的style.xml,路径: 266 | adt_bundle/sdk/platforms/android-19/data/res/values/styles.xml 267 | 268 | --参考系统的themes.xml,路径: 269 | adt_bundle/sdk/platforms/android-19/data/res/values/themes.xml 270 | 271 | ###引用样式:在指定UI控件的style属性引用指定样式 272 | 273 | 引用样式前: 274 | 280 | 281 | 282 | 引用样式后: 283 | 286 | 287 | ###样式的继承 288 | ####parent属性方式 289 | 290 | 291 | 297 | 298 | 299 | 300 | ####前辍方式 301 | 302 | 305 | 306 | 309 | 310 | 311 | 312 | ##theme 主题 313 | 314 | ###作用:主要是为了让应用中所有UI控件的样式保持一致,如所有界面的字体大小、颜色等 315 | 316 | ### 应用引用样式 317 | ### activity引用样式 318 | 319 | ###常用的系统主题 320 | 321 | android:style/Theme.Holo.Light 白底黑字 322 | android:style/Theme.Holo 黑底白字 323 | android:style/Theme.NoTitleBar.Fullscreen 无标题栏且全屏 324 | 325 | 326 | ###消除应用启动闪黑屏 327 | 328 | 329 | 332 | 333 | 334 | ------------------------ 335 | 336 | 常见颜色示例: 337 | res/values/colors.xml: 338 | 339 | 340 | 341 | #ffffff 342 | #fffff0 343 | #ffffe0 344 | #ffff00 345 | #fffafa 346 | #fffaf0 347 | #fffacd 348 | #fff8dc 349 | #fff5ee 350 | #fff0f5 351 | #ffefd5 352 | #ffebcd 353 | #ffe4e1 354 | #ffe4c4 355 | #ffe4b5 356 | #ffdead 357 | #ffdab9 358 | #ffd700 359 | #ffc0cb 360 | #ffb6c1 361 | #ffa500 362 | #ffa07a 363 | #ff8c00 364 | #ff7f50 365 | #ff69b4 366 | #ff6347 367 | #ff4500 368 | #ff1493 369 | #ff00ff 370 | #ff00ff 371 | #ff0000 372 | #fdf5e6 373 | #fafad2 374 | #faf0e6 375 | #faebd7 376 | #fa8072 377 | #f8f8ff 378 | #f5fffa 379 | #f5f5f5 380 | #f5f5dc 381 | #f5deb3 382 | #f4a460 383 | #f0ffff 384 | #f0fff0 385 | #f0f8ff 386 | #f0e68c 387 | #f08080 388 | #eee8aa 389 | #ee82ee 390 | #e9967a 391 | #e6e6fa 392 | #e0ffff 393 | #deb887 394 | #dda0dd 395 | #dcdcdc 396 | #dc143c 397 | #db7093 398 | #daa520 399 | #da70d6 400 | #d8bfd8 401 | #d3d3d3 402 | #d3d3d3 403 | #d2b48c 404 | #d2691e 405 | #cd853f 406 | #cd5c5c 407 | #c71585 408 | #c0c0c0 409 | #bdb76b 410 | #bc8f8f 411 | #ba55d3 412 | #b8860b 413 | #b22222 414 | #b0e0e6 415 | #b0c4de 416 | #afeeee 417 | #adff2f 418 | #add8e6 419 | #a9a9a9 420 | #a9a9a9 421 | #a52a2a 422 | #a0522d 423 | #9932cc 424 | #98fb98 425 | #9400d3 426 | #9370db 427 | #90ee90 428 | #8fbc8f 429 | #8b4513 430 | #8b008b 431 | #8b0000 432 | #8a2be2 433 | #87cefa 434 | #87ceeb 435 | #808080 436 | #808080 437 | #808000 438 | #800080 439 | #800000 440 | #7fffd4 441 | #7fff00 442 | #7cfc00 443 | #7b68ee 444 | #778899 445 | #778899 446 | #708090 447 | #708090 448 | #6b8e23 449 | #6a5acd 450 | #696969 451 | #696969 452 | #66cdaa 453 | #6495ed 454 | #5f9ea0 455 | #556b2f 456 | #4b0082 457 | #48d1cc 458 | #483d8b 459 | #4682b4 460 | #4169e1 461 | #40e0d0 462 | #3cb371 463 | #32cd32 464 | #2f4f4f 465 | #2f4f4f 466 | #2e8b57 467 | #228b22 468 | #20b2aa 469 | #1e90ff 470 | #191970 471 | #00ffff 472 | #00ffff 473 | #00ff7f 474 | #00ff00 475 | #00fa9a 476 | #00ced1 477 | #00bfff 478 | #008b8b 479 | #008080 480 | #008000 481 | #006400 482 | #0000ff 483 | #0000cd 484 | #00008b 485 | #000080 486 | #000000 487 | 488 | -------------------------------------------------------------------------------- /Android/存储.md: -------------------------------------------------------------------------------- 1 | #Store 2 | ###Android上存储有以下几种方式: 3 | - SharedPreferences 4 | - 文件 5 | - Sqlite 6 | 7 | 8 | ##SharedPreferences 9 | SharedPreferences是Android平台上一个轻量级的存储类,用来保存应用的一些**常用配置**,比如Activity状态,Activity暂停时,将此activity的状态保存到SharedPereferences中;当Activity重载,系统回调方法onSaveInstanceState时,再从SharedPreferences中将值取出。 10 | 最终是以xml方式来保存. 11 | 文件存储位置: 12 | 目录:`data/data/{包名}/shared_prefs` 13 | 14 | 15 | 存数据: 16 | 17 | 得到共享参数对象:SharedPreferences pref = getSharedPreference(); 18 | SharedPreferences.Edit edit = pref.edit(); 19 | edit.putInt("num",3);//键值对 20 | edit.putXXX();//可以存储Long、Int、String等类型数据 21 | edit.commit();//提交写入数据 22 | 23 | 获取共享参数: 24 | 25 | SharedPreferences pref = getSharedPreference(); 26 | pref.getInt("num",default);//通过键去获取值,获取不到使用默认值 27 | 28 | 示例: 29 | 30 | 使用共享参数保存数据 31 | 32 | public void saveData() 33 | { 34 | //获取共享参数对象 35 | //第一个参数是共享参数文件的名字 36 | //第二个参数是对该文件的操作模式 37 | SharedPreferences shared = getSharedPreferences("configration",Context.MODE_PRIVATE); 38 | 39 | //获取共享参数编辑对象 40 | SharedPreferences.Editor edit = shared.edit(); 41 | 42 | //使用编辑对象存储数据 43 | edit.putFloat("fontSize", fontSize); 44 | edit.putInt("fontColor", fontColor); 45 | edit.putInt("backColor", backColor); 46 | 47 | //提交 48 | edit.commit(); 49 | } 50 | 51 | 使用共享参数读取数据 52 | 53 | public void readData() 54 | { 55 | //获取共享参数对象 56 | //第一个参数是被读取的共享参数文件 57 | SharedPreferences shared = getSharedPreferences("configration", Context.MODE_PRIVATE); 58 | 59 | Float fontSize = shared.getFloat("fontSize", 25); 60 | Int fontColor = shared.getInt("fontColor", Color.GRAY); 61 | Int backColor = shared.getInt("backColor", Color.WHITE); 62 | 63 | } 64 | 65 | ##文件存储 66 | 文件存储主要是存储在SD卡上 67 | 使用SD卡,需要拥有**权限**: 68 | 69 | 70 | 71 | 72 | 73 | 那么就需要获取SD卡的一些属性,常用的方法如下: 74 | 75 | 获取外部存储空间的目录 76 | 77 | `Environment.getExternalStorageDirectory() ` 78 | 79 | 判断扩展卡是否挂载 80 | 81 | /** 82 | * 判断扩展卡是否挂载 83 | * 84 | * @return 85 | */ 86 | public static boolean isMounted() { 87 | String state = Environment.getExternalStorageState(); 88 | return state.equals(Environment.MEDIA_MOUNTED); 89 | } 90 | 91 | 获取扩展卡的剩余空间 92 | 93 | /** 94 | * 获取扩展卡的剩余空间,并返回,上层如果需要判断空间够不够用,可以在上层处理 95 | */ 96 | public static int getAble() 97 | { 98 | //文件系统状态管理对象 99 | StatFs fs = new StatFs(Environment.getExternalStorageDirectory().getAbsolutePath()); 100 | int count = fs.getFreeBlocks();//空闲的数据块个数 101 | int size = fs.getBlockSize();//返回每个数据块的大小 102 | 103 | //剩余空间大小 104 | long total = count*size;//单位是字节 105 | int t = (int) (total/1024/1024);//返回单位为M(以便处理) 106 | return t; 107 | } 108 | 109 | 对图片的读取和写入: 110 | 111 | //用到的常量: 112 | public static final int FORMAT_PNG = 1; 113 | public static final int FORMAT_JPEG = 2; 114 | public static final String IMAGE_URL = Environment 115 | .getExternalStorageDirectory() + "/images"; 116 | 117 | /** 118 | * 根据文件的下载路径获取文件名 119 | * 120 | * @param url 121 | * @return 122 | */ 123 | public static String getFileName(String url) { 124 | return url.substring(url.lastIndexOf("/") + 1); 125 | } 126 | 127 | /** 128 | * 保存图片到扩展卡的功能 129 | * 130 | * @throws IOException 131 | */ 132 | public static void saveImage(String url, byte[] data) throws IOException { // 判断扩展卡是否挂载 133 | if (!isMounted()) 134 | return; 135 | // 判断存储目录是否存在 136 | File dir = new File(IMAGE_URL); 137 | if (!dir.exists()) 138 | dir.mkdirs(); 139 | 140 | // 把图片数据写入到一个图片文件 141 | FileOutputStream fos = new FileOutputStream(new File(dir, 142 | getFileName(url))); 143 | fos.write(data); 144 | 145 | fos.close(); 146 | 147 | } 148 | 149 | 150 | /** 151 | * 保存图片到扩展卡的功能 152 | * 153 | * @throws FileNotFoundException 154 | */ 155 | public static void saveImage(String url, Bitmap bitmap, int format) 156 | throws FileNotFoundException { 157 | // 判断扩展卡是否挂载 158 | if (!isMounted()) 159 | return; 160 | // 判断存储目录是否存在 161 | File dir = new File(IMAGE_URL); 162 | if (!dir.exists()) 163 | dir.mkdirs(); 164 | // 把图片数据写入到一个图片文件 165 | FileOutputStream fos = new FileOutputStream(new File(dir, 166 | getFileName(url))); 167 | 168 | // 图片的压缩 CompressFormat.PNG:压缩之后的格式 169 | bitmap.compress(format == 1 ? CompressFormat.PNG : CompressFormat.JPEG, 170 | 100, fos); 171 | } 172 | 173 | /** 174 | * 从扩展卡读取图片的功能 175 | */ 176 | public static Bitmap readImage(String url) { 177 | // 判断扩展卡是否挂载 178 | if (!isMounted()) 179 | return null; 180 | 181 | String filename = getFileName(url); 182 | File file = new File(IMAGE_URL, filename); 183 | Bitmap bitmap = null; 184 | if(file.exists()) 185 | bitmap = BitmapFactory.decodeFile(file.getAbsolutePath()); 186 | return bitmap; 187 | } 188 | 189 | 清空扩展卡 缓存目录中的内容的功能 190 | 191 | /** 192 | * 清空扩展卡 缓存目录中的内容的功能 193 | */ 194 | public static void clear() { 195 | // 判断扩展卡是否挂载 196 | if (!isMounted()) 197 | return; 198 | File dir = new File(IMAGE_URL); 199 | if (dir.exists()) { 200 | File[] arr = dir.listFiles(); 201 | for(File f:arr) 202 | { 203 | f.delete(); 204 | } 205 | } 206 | } 207 | 208 | ##Sqlite 209 | 外部创建的数据库文件导入,需要放入/mnt/sdcard/cache/db/目录下 210 | 可使用adb命令导入: 211 | `adb push xxx.db /mnt/sdcard/cache/db` 212 | 需要加权限: 213 | 214 | 215 | 216 | 217 | 使用Sqlite主要就是下面两个类: 218 | **SQLiteDatabase**:数据库操作类 219 | **SQLiteOpenHelper**:数据库管理类 220 | 221 | ###SQLiteDatabase使用示例: 222 | 223 | SQLiteDatabase db = SQLiteDatabase.openDatabase(DB_PATH, null, SQLiteDatabase.OPEN_READWRITE); 224 | 225 | #### insert 226 | 227 | 第一种方法: 228 | 229 | //db.execSQL("insert into student values(?,?,?,?,?)",new Object[]{4,"liuneng","男",58,"666"}); 230 | 231 | 第二种方法(推荐使用): 232 | 233 | ContentValues values = new ContentValues(); 234 | values.put("_id", 5); 235 | values.put("name", "Jack"); 236 | values.put("sex", "女"); 237 | values.put("age", 21); 238 | values.put("tel","032840329"); 239 | 240 | long num = db.insert("student", null,values);//num返回的是插入的数据条数,返回-1表示插入出错。 241 | 242 | #### update 243 | 第二种方法: 244 | 245 | //db.execSQL("update student set age=? where _id=?",new Object[]{59,_id}); 246 | 247 | 第二种方法: 248 | 249 | ContentValues value = new ContentValues(); 250 | value.put("name", "Jack-new"); 251 | value.put("sex", "女"); 252 | value.put("age", 22); 253 | value.put("tel","999"); 254 | 255 | int count = db.update("student", value,"_id="+_id, null);、、count表示更新的记录数,-1表示更新出错 256 | 257 | #### delete 258 | 第一种方法: 259 | 260 | //db.execSQL("delete from student where _id=?",new Object[]{_id}); 261 | 262 | 第二种方法: 263 | 264 | int coun = db.delete("student", "_id="+_id,null); 265 | 266 | ####使用Cursor获取结果集 267 | 268 | public void loadData() { 269 | //打开数据库 270 | //第一个参数是被打开的数据库文件的路径 271 | //第二个参数是管理游标的工厂类对象 272 | //第三个操作数据库的方式 273 | SQLiteDatabase db = SQLiteDatabase.openDatabase(DB_PATH, null, SQLiteDatabase.OPEN_READONLY); 274 | 275 | //查询表中的数据 276 | //查询的结果集是 Cursor类型的 277 | Cursor cursor = db.rawQuery("select * from student",null); 278 | 279 | //从结果集中获取记录--游标指向第一条记录的上边 所以需要让游标下移,判断是否有记录 280 | List datas= new ArrayList<>(); 281 | while(cursor.moveToNext()) 282 | { 283 | //使用游标获取记录中每个字段上的值 284 | int id = cursor.getInt(cursor.getColumnIndex("_id")); 285 | String name = cursor.getString(cursor.getColumnIndex("name")); 286 | int age = cursor.getInt(cursor.getColumnIndex("age")); 287 | String sex = cursor.getString(cursor.getColumnIndex("sex")); 288 | String tel = cursor.getString(cursor.getColumnIndex("tel")); 289 | Student stu = new Student(); 290 | stu.set_id(""+id); 291 | stu.setName(name); 292 | stu.setAge(age); 293 | stu.setSex(sex); 294 | stu.setTel(tel); 295 | datas.add(stu); 296 | } 297 | 298 | db.close();//关闭数据库 299 | 300 | } 301 | 302 | ###SQLiteOpenHelper 303 | 管理数据库的类(使用它创建的数据库在内部存储里,不在sd卡,不需要对sd卡的读写权限) 304 | 305 | 管理数据库的创建,删除, 306 | 数据库版本的升级 307 | 308 | 示例: 309 | 310 | public class DBHelper extends SQLiteOpenHelper { 311 | 312 | public DBHelper(Context context) 313 | { 314 | //第二个参数是数据库的名字 315 | //第三个参数是管理游标的工厂类对象 316 | //第四个参数是当前数据库的版本 317 | super(context, "user.db", null, 1); 318 | } 319 | 320 | //创建数据库时执行该方法 321 | //表中字段必须含有一个 _id 322 | @Override 323 | public void onCreate(SQLiteDatabase db) { 324 | 325 | db.execSQL("create table t_user(_id integer primary key,name text,age int,tel text)"); 326 | 327 | } 328 | 329 | //数据库版本升级时执行该方法 330 | @Override 331 | public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 332 | 333 | if(newVersion>oldVersion) 334 | { 335 | db.execSQL("drop table if exists t_user"); 336 | } 337 | } 338 | } 339 | 340 | 调用获取创建数据库并获取读写: 341 | 342 | public void addData()//点击按钮添加一条记录 343 | { 344 | //因为是添加数据,所以获取到可写的数据库操作对象 345 | SQLiteDatabase db = dbHelper.getWritableDatabase(); 346 | 347 | ContentValues value = new ContentValues(); 348 | value.put("name", "Tom"); 349 | value.put("age", 23); 350 | value.put("tel", "120"); 351 | 352 | int num = (int) db.insert("t_user", null, value); 353 | if(num!=-1) 354 | Toast.makeText(this, "添加成功", Toast.LENGTH_SHORT).show(); 355 | 356 | loadData(); 357 | } 358 | 359 | public void loadData()//加载数据 360 | { 361 | SQLiteDatabase db = dbHelper.getReadableDatabase(); 362 | private String[] columns={"_id","name","age","tel"}; 363 | cursor = db.query("t_user", columns, null, null, null, null, null); 364 | 365 | //游标中的数据变化了,需要切换适配器的数据源 366 | adapter.swapCursor(cursor); 367 | 368 | //db.close();不能关,否则cursor中的数据就没了 369 | } 370 | 371 | 372 | -------------------------------------------------------------------------------- /Android工具使用/ADB.md: -------------------------------------------------------------------------------- 1 | #ADB 2 | ##常见问题集 3 | ###adb无法连接 4 | 5 | adb server is out of date. killing... 6 | ADB server didn't ACK 7 | * failed to start daemon * 8 | error: unknown host service 9 | 10 | 或者 11 | 12 | * daemon not running. starting it now * 13 | ADB server didn't ACK 14 | * failed to start daemon * 15 | 16 | 当出现上面问题就是`其他的进程占用了adb的5037端口`,导致adb服务不能开启 17 | 18 | **解决方法:** 19 | 20 | **查看5037端口被谁占用了** 21 | 开始--运行--CMD 到命令提示符,输入 `netstat -aon|findstr "5037"` 22 | 23 | C:\Users\wswenyue\Downloads>netstat -aon|findstr "5037" 24 | TCP127.0.0.1:5037 0.0.0.0:0 LISTENING 5076 25 | 26 | 看到是(PID)5076这个进程占用了,接着**查看该进程是不是adb进程**: 27 | 28 | `tasklist|findstr "2748" ` 29 | 30 | C:\Users\wswenyue\Downloads>tasklist|findstr "5076" 31 | shuame_helper.exe 5076 Console1 6,216 K 32 | 33 | **不是adb进程去任务管理器把该进程关了。重启adb就好了** 34 | 35 | ------------------- 36 | 37 | 38 | -------------------------------------------------------------------------------- /Android第三方库/picasso.md: -------------------------------------------------------------------------------- 1 | #picasso 毕加索 2 | ##介绍: 3 | Square公司开源的一个Android图形缓存库 4 | > A powerful image downloading and caching library for Android 5 | 6 | 项目地址: https://github.com/square/picasso 7 | 文档: http://square.github.io/picasso/ 8 | API: http://square.github.io/picasso/javadoc/index.html 9 | 10 | 如果使用ProGuard要加入如下依赖: 11 | 12 | -dontwarn com.squareup.okhttp.** 13 | 14 | 优点及特性: 15 | 以下在Picasso中会自动处理,无需使用者操心: 16 | 17 | - Handling ImageView recycling and download cancelation in an adapter. 18 | - Complex image transformations with minimal memory use. 19 | - Automatic memory and disk caching. 20 | 21 | ##使用: 22 | ###添加jar: 23 | Gradle: 24 | 25 | compile 'com.squareup.picasso:picasso:2.5.2' 26 | 27 | Maven: 28 | 29 | ```maven 30 | 31 | com.squareup.picasso 32 | picasso 33 | 2.5.2 34 | 35 | ``` 36 | 37 | ###使用方法 38 | 最简单的使用: 39 | 40 | ```java 41 | Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView); 42 | ``` 43 | 44 | 可以加载的资源很多: 45 | 46 | `Resources, assets, files, content providers are all supported as image sources.` 47 | 48 | ```java 49 | Picasso.with(context).load(R.drawable.landing_screen).into(imageView1); 50 | Picasso.with(context).load("file:///android_asset/DvpvklR.png").into(imageView2); 51 | Picasso.with(context).load(new File(...)).into(imageView3); 52 | ``` 53 | 54 | 在适配器中使用: 55 | 56 | ```java 57 | @Override 58 | public void getView(int position, View convertView, ViewGroup ) { 59 | 60 | Picasso.with(context).load(url).into(view);//这里注意Picasso.with(context)应该提取到外面,不应该被重复执行,否则可能出现Bug 61 | } 62 | ``` 63 | 设置图片的大小及填充方式 64 | 65 | ```java 66 | Picasso.with(context) 67 | .load(url) 68 | .resize(50, 50) //设置大小 69 | .centerCrop() //设置填充方式,这个是推荐的 70 | .into(imageView) 71 | ``` 72 | 73 | 指定加载完成之前显示的图片和加载出错显示的图片: 74 | 75 | ```java 76 | Picasso.with(context) 77 | .load(url) 78 | .placeholder(R.drawable.user_placeholder) 79 | .error(R.drawable.user_placeholder_error) 80 | .into(imageView); 81 | ``` 82 | 83 | 定制图片的转换方式 84 | 85 | ```java 86 | public class CropSquareTransformation implements Transformation { 87 | @Override public Bitmap transform(Bitmap source) { 88 | int size = Math.min(source.getWidth(), source.getHeight()); 89 | int x = (source.getWidth() - size) / 2; 90 | int y = (source.getHeight() - size) / 2; 91 | Bitmap result = Bitmap.createBitmap(source, x, y, size, size);//这个是用来裁剪的图片的 92 | if (result != source) { 93 | source.recycle();//这里必须回收 94 | } 95 | return result; 96 | } 97 | 98 | @Override public String key() { //这个方法返回的key应该是唯一的,用来作为缓存的键 99 | return "square()"; 100 | } 101 | } 102 | ``` 103 | 使用变换: 104 | 105 | ```java 106 | picasso.load(R.drawable.download) 107 | .skipMemoryCache() //不要把加载的图片放入缓存,也不要从缓存中取图片 108 | .transform(new CropSquareTransformation()) //执行自定义变换 109 | .into(view); 110 | ``` 111 | 112 | 加载图片并自定义动作 113 | 114 | ```java 115 | Target target = new Target(){ 116 | @Override 117 | public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom loadedFrom) { 118 | //当图片加载成功时调用,bitmap是加载的图片,loadFrom 标明图片的来源是网络、内存还是磁盘 119 | //可以在里面执行把图片保存到本地的操作 120 | } 121 | @Override 122 | public void onBitmapFailed(Drawable errorDrawable) { //当图片加载失败时调用 123 | } 124 | @Override 125 | public void onPrepareLoad(Drawable placeHolderDrawable) { //当任务被提交时调用 126 | } 127 | }; 128 | picasso.load(new File("/1.jpg")).into(target); //指定target任务加载图片 129 | ``` 130 | 131 | 加载图片到 ImageView: 132 | 133 | ```java 134 | ImageView view = null; 135 | Picasso picasso = Picasso.with(this); 136 | picasso.setIndicatorsEnabled(true); //开启调模式,它能够在图片左上角显示小三角形,这个小三角形的颜色标明了图片的来源:网络、内存缓存、磁盘缓存 137 | picasso.setLoggingEnabled(true); //打开日志,即log中会打印出目前下载的进度、情况 138 | picasso.load("http://xxx.jpg") //可以是本地图片或网络图片 139 | .placeholder(R.drawable.placeholder) //当图片正在加载时显示的图片(optional) 140 | .error(R.drawable.error) //当图片加载失败时显示的图片(optional) 141 | .into(view, new Callback() { //将图片下载完后放进view中,回调是可选的 142 | @Override 143 | public void onSuccess() { 144 | //加载图片成功时回调 145 | } 146 | @Override 147 | public void onError() { 148 | //加载图片失败时回调 149 | } 150 | }); 151 | 152 | ``` 153 | 154 | 开发者可以打开调试功能: 155 | 打开之后如果图片是从网络中获得,则图片左上角会有红色三角形;如果图片从磁盘获得,则图片左上角会有黄色三角形;如果图片从内存获得,则图片左上角会有绿色三角形。如图所示: 156 | 157 | ![](http://square.github.io/picasso/static/debug.png) 158 | 159 | 160 | 161 | -------------------------------------------------------------------------------- /Android第三方库/推送-极光推送.md: -------------------------------------------------------------------------------- 1 | #推送的作用 2 | - 提升用户忠诚度 3 | - 提高用户留存率 4 | - 提高用户量 5 | 6 | # 极光推送 7 | #### [极光推送官网](http://jpush.cn "极光推送") 8 | #### [开发文档](http://jpush.cn "极光推送") 9 | 10 | ##极光推送消息分类: 11 | - 通知 12 | - 直接在通知栏显示,可以设置点击之后的操作(比如打开Activity、服务等) 13 | - 自定义消息 14 | - 自定义消息不使用通知显示,服务接受到后直接发送广播,有你自己的应用接受广播并处理 15 | - 富媒体 16 | - 富媒体可以使用模板,图文消息,收到后也是以通知显示,点击显示图文内容 17 | - 附加字段: 通知和自定义消息均可添加附加字段,接受到的附加字段的格式是:JSON字符串 18 | 19 | ##推送可以使用群组分类发送: 20 | ###使用Tag标签 21 | 按照同一类标签的用户发送消息 22 | ###使用别名 23 | 每个手机客户端只能有一个别名,按照别名则是一对一的推送 24 | 25 | 26 | ## 推送系统的流程 27 | 28 | ![推送流程](http://7xj2yt.com1.z0.glb.clouddn.com/android_JPush.png) 29 | 30 | ## 推送系统结构 31 | ![推送系统结构](http://7xj2yt.com1.z0.glb.clouddn.com/android_JPush_推送系统结构.png) 32 | 33 | - 服务器主动推送给客户端 34 | - 客户端后台Service接受 35 | - Service发送通知给BroadcastReceiver 36 | 37 | ## 极光推送快速使用 38 | ###注册账号、创建应用、获取App Key 39 | ###下载默认Demo工程 40 | 该工程已经自动将自己的AppKey整合了。 41 | 不过该项目是eclipse项目,对于AndroidStudio需要整合 42 | ###整合项目到AndroidStudio中 43 | 1. JPushDemo src 内部的源代码 复制到main/java 内部 44 | 2. JPushDemo中 libs中的jar包,复制到app/libs 45 | 3. Demo中libs内部的文件夹 (SO库),复制到 src/main/jniLibs 46 | 4. 资源res目录,复制到as资源res,如果没有事初始化工程直接覆盖就行,如果不是,则需要小心。 47 | 5. 清单文件:如果清单文件已经存在,并且也包含了内容,那么就从清单文件复制内容;如果是一个空的工程,直接覆盖 48 | 49 | ###整合后的AndroidStudio Demo源码下载 50 | [请戳我。](http://7xnhm8.com1.z0.glb.clouddn.com/android_Jwenyue.zip) 51 | 52 | ###代码步骤 53 | 1. Application 要进行JPush的初始化,使用JPushInterface.init(Context)初始化 54 | 2. MyReceiver类,实现了通知信息的接收。 55 | 3. 实际的所有接收的业务逻辑,都是由MyReceiver来完成。 56 | 4. MyReceiver处理的操作: 57 | - 手机与推送服务器注册成功,会收到通知regId 58 | - 接收自定义消息(可以包含JSON) 59 | - 可以检测用户点击通知,跳转通知对应的页面。 60 | 61 | #[更多详情](http://7xnhm8.com1.z0.glb.clouddn.com/android_JPush.pdf) 62 | 63 | 64 | ---------- 65 | 66 | #百度云推送 67 | 百度云推送也是和上面的极光推送差不多 68 | 资料链接: 69 | 70 | [百度云推送官网](http://push.baidu.com/) 71 | 72 | [向导](http://push.baidu.com/doc/guide/index) 73 | [开发文档](http://push.baidu.com/doc/android/api) 74 | 75 | [百度云推送Demo整合为AndroidStudio项目----请下载之后记得修改清单文件里面的AppKey](http://7xnhm8.com1.z0.glb.clouddn.com/android_BDPushDemo.zip) 76 | 77 | -------------------------------------------------------------------------------- /Android第三方库/支付及其项目集成.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wswenyue/note/a7df9fc77f72331270f228576a056501c0d06ba6/Android第三方库/支付及其项目集成.md -------------------------------------------------------------------------------- /Android第三方库/购物车设计.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wswenyue/note/a7df9fc77f72331270f228576a056501c0d06ba6/Android第三方库/购物车设计.md -------------------------------------------------------------------------------- /File操作.md: -------------------------------------------------------------------------------- 1 | #File及Properties类的使用 2 | > 说明:File类代表系统文件或目录,即磁盘上的文件和目录都是通过File类的实例表示 3 | 4 | ###构造文件对象 5 | 6 | File(File dir, String name) //第一个参数:指定所在目录的文件对象;第二个参数:包含扩展名的文件名 7 | File(String dirPath, String name) //第一个参数:指定所在目录的路径;第二个参数:包含扩展名的文件名 8 | File(String path) //指定文件的绝对路径 9 | File(URI uri) //指定资源唯一标识的对象 10 | 11 | ###访问文件的属性 12 | 13 | public boolean canRead() 是否可读 14 | public boolean canWrite() 是否可写 15 | public boolean exists() 文件或目录是否存在 16 | public boolean isDirectory() 是否目录/路径 17 | public boolean isFile() 是否是文件 18 | public boolean isHidden() 是否是隐藏的 19 | public boolean isHidden() 是否是隐藏的 20 | public long length()获取文件长度,单位:字节 21 | public String getName() 获取文件名称 22 | public String getPath() 获取文件路径 23 | public String getAbsolutePath() 返回此File对象的绝对路径 24 | public String getParent() 获取父目录,没有则为null 25 | public static final String separator 文件路径分隔符(在 UNIX 系统上,此字段的值为 '/';在 Microsoft Windows 系统上,它为 '\\') 26 | 27 | ###对文件的操作 28 | 29 | public boolean createNewFile() //不存在时创建此文件对象所代表的空文件 30 | public boolean delete() //删除文件。如果是目录必须是空才能删除 31 | public boolean mkdir()  //创建此抽象路径名指定的目录 32 | public boolean mkdirs() //创建此抽象路径名指定的目录,包括所有必需但不存在的父目录 33 | public boolean renameTo(File dest) //重新命名此抽象路径名表示的文件 34 | 35 | ###浏览目录中的文件和子目录 36 | 37 | public String[] list()返回此目录中的文件名和目录名的数组 38 | public File[] listFiles()返回此目录中的文件和目录的File实例数组 39 | public File[] listFiles(FilenameFilter filter)返回此目录中满足指定过滤器的文件和目录 40 | java.io.FilenameFilter接口:实现此接口的类实例可用于过滤文件名 41 | 42 | ##Properties类的使用 43 | > 说明:HashTable的子类,属于集合类,存储属性类型的键值对,键和值默认都是 String 44 | 45 | 注意:**是集合中可以和流结合使用的一个集合类** 46 | 47 | 构造方法: 48 | 49 | Properties() 50 | Properties(Properties properties) 51 | 52 | 加载方法: 53 | 54 | load(InputStream in) 55 | load(Reader in) 56 | loadFromXML(InputStream in) 57 | 58 | 保存方法: 59 | 60 | store(OutputStream out, String comment) 61 | store(Writer writer, String comment) 62 | storeToXML(OutputStream os, String comment, String encoding) 63 | storeToXML(OutputStream os, String comment) 64 | 65 | 打印方法: 66 | 67 | list(PrintWriter out) 68 | list(PrintStream out) 69 | 70 | 获取方法: 71 | 72 | Enumeration propertyNames() 73 | String getProperty(String name) 74 | String getProperty(String name, String defaultValue) 75 | Set stringPropertyNames() 76 | 77 | 修改方法: 78 | 79 | Object setProperty(String name, String value) 80 | 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /Home.md: -------------------------------------------------------------------------------- 1 | ##这里是我记录学习的笔记 2 | ###Android 3 | 4 | > ### 基础知识 5 | 6 | 知识点|知识点|知识点 7 | :--:|:--:|:--: 8 | [ActionBar](./ActionBar "ActionBar")|[Activity](./Activity "Activity")|[Broadcast](./Broadcast) 9 | [ContentProvider与ContentResolver](./ContentProvider与ContentResolver)|[Handler](./Handler)|[Loader](./Loader) 10 | [MediaPlayer](./MediaPlayer)|[Service](./Service)|[Timer](./Timer) 11 | [UI_Fragment](./UI_Fragment)|[UI_Notification](./UI_Notification)|[UI_Resources](./UI_Resources) 12 | [存储](./存储)| 13 | 14 | 15 | > ###高级应用 16 | 17 | [Fragment高级使用及问题解决](./Fragment高级使用及问题解决) 18 | 19 | 20 | ###Android的第三方库 21 | [picasso](./picasso "picasso") 22 | 23 | ####推送 24 | - [极光推送](./推送-极光推送 "推送-极光推送") 25 | 26 | ###Android工具使用 27 | [ADB](./ADB "ADB") 28 | 29 | ###issue 30 | [多线程相关](./多线程相关 "多线程相关") 31 | 32 | [获取屏幕相关高度](./获取屏幕相关高度 "获取屏幕相关高度") 33 | 34 | [获取视图控件的宽高](./获取视图控件的宽高 "获取视图控件的宽高") 35 | 36 | [视图焦点的控制、listview中子控件抢焦点或获得不到焦点的问题解决](./视图焦点问题 "视图焦点问题") 37 | 38 | 39 | 40 | --- 41 | 42 | ###java语言基本知识 43 | 44 | 知识点|知识点|知识点|知识点 45 | :--:|:--:|:--:|:--: 46 | [java基础知识1](./javaBasic1)|[java基础知识2](./javaBasic2)|[java基础知识3](./javaBasic3)|[java基础知识4](./javaBasic4) 47 | [java基础知识5](./javaBasic5)| 48 | [IO流](./IO流)|[IO流和文件的相关练习](./IO流和文件的相关练习) 49 | [Socket](./Socket)|[常用算法](./常用算法)|[概念区别](./概念区别)|[设计模式](./设计模式) 50 | [正则](./正则)|[SQL](./SQL) -------------------------------------------------------------------------------- /IO流.md: -------------------------------------------------------------------------------- 1 | #IO流 2 | --- 3 | ##总览 4 | 5 | 流的分类: 6 | 7 | 类别|分类1|分类2 8 | ---|---|--- 9 | 单位|字节流|字符流 10 | 流向|输入流|输出流 11 | 功能|节点流|处理流 12 | 13 | 14 | 流与流之间的转换关系: 15 | 16 | ![转换](http://7xj2yt.com1.z0.glb.clouddn.com/java_IO流.png) 17 | 18 | ###IO流图 19 | 20 | 流名称|字节输入|字节输出|字符输入|字符输出 21 | ---|---|----|----|---- 22 | 4大基类 |InputStream |OutputStream|Reader|Writer 23 | **文件流**| FileInputStream| FileOutputStream|FileReader| FileWriter 24 | **转换流**|-|-|InputStreamReader| OutputStreamWriter 25 | System| System.in|System.out|-|- 26 | 打印流|-|PrintStream|-| PrintWriter 27 | **缓存流**|BufferedInputStream|BufferedOutputStream|BufferedReader|BufferedWriter 28 | 数据流 | DataInputStream |DataOutputStream|-|- 29 | **内存流**|ByteArrayInputStream|ByteArrayOutputStream|-|- 30 | 对象流|ObjectInputStream| ObjectOutputStream|-|- 31 | 随机访问流 |-|RandomAccessFile|-|- 32 | 33 | ---- 34 | ###IO流类思维导图 35 | ![IO流类思维导图](http://7xj2yt.com1.z0.glb.clouddn.com/java_IO.bmp) 36 | 37 | ----- 38 | 39 | ##四大抽象类 40 | 41 | ### InputStream 42 | 43 | > 说明:继承自InputStream的流都是用于向程序中输入数据的,且数据的单位为字节(8位) 44 | 45 | 核心方法: 46 | 47 | public abstract int read() //从输入流中读取数据的下一个字节, 返回读到的字节值.若遇到流的末尾,返回-1 48 | public int read(byte[] b) //从输入流中读取 b.length 个字节的数据并存储到缓冲区数组b中.返回的是实际读到的字节总数 49 | public int read(byte[] b, int off, int len) //读取 len 个字节的数据,并从数组b的off位置开始写入到这个数组中 50 | public void close() //关闭此输入流并释放与此流关联的所有系统资源 51 | public int available() //返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数 52 | public long skip(long n) //跳过和丢弃此输入流中数据的 n 个字节,返回实现路过的字节数。 53 | 54 | ### OutputStream 55 | 56 | > 说明:继承自OutputStream的流是程序用于向外输出数据的,且数据的单位为字节(8位) 57 | 58 | 核心方法: 59 | 60 | public abstract void write(int b) //将指定的字节写入此输出流 61 | public void write(byte[] b) //将 b.length 个字节从指定的 byte 数组写入此输出流 62 | public void write(byte[] b, int off, int len) //将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流 63 | public void flush() //刷新此输出流并强制写出所有缓冲的输出字节 64 | pulbic void close() //关闭此输出流并释放与此流有关的所有系统资源 65 | 66 | ### Reader 67 | 68 | > 说明:继承自Reader的流都是用于向程序中输入数据的,且数据的单位为字符(16位) 69 | 70 | 核心方法: 71 | 72 | public int read() //读取单个字符的编码,返回作为整数读取的字符,如果已到达流的末尾返回-1 73 | public int read(char[] cbuf) //将字符读入数组,返回读取的字符数 74 | public abstract int read(char[] cbuf, int off, int len) //读取 len 个字符的数据,并从数组cbuf的off位置开始写入到这个数组中 75 | public abstract void close() //关闭该流并释放与之关联的所有资源 76 | public long skip(long n) //跳过n个字符 77 | int available() //还可以有多少能读到的字节数 78 | 79 | 80 | ### Writer 81 | 82 | > 说明:继承自Writer的流是程序用于向外输出数据的,且数据的单位为字符(16位) 83 | 84 | 核心方法: 85 | 86 | public void write(int c) //写入单个字符 87 | public void write(char[] cbuf) //写入字符数组 88 | public abstract void write(char[] cbuf, int off, int len) //写入字符数组的某一部分 89 | public void write(String str) //写入字符串 90 | public void write(String str, int off, int len) //写字符串的某一部分 91 | public abstract void close() //关闭此流,但要先刷新它 92 | public abstract void flush() //刷新该流的缓冲,将缓冲的数据全写到目的地 93 | 94 | ------- 95 | 96 | ##节点流 97 | ###文件流 98 | > 说明:文件流主要用来操作文件 99 | 100 | - **FileInputStream**:继承自InputStream 101 | 102 | - **FileOutputStream**继承自OutputStream 103 | FileOutputStream(String name, boolean append) 指定文件名和是否以追回方式写入 104 | 105 | - **FileReader**继承自Reader 106 | 核心方法: 107 | 108 | 1、构造方法 109 | FileReader(File file) 110 | FileReader(String fileName) 111 | 2、成员方法 112 | int read() //每次读取一个字符,末尾-1返回值就是读入的内容 113 | int read(char[] cbuf) //每次读取一组字符,最多读数组长度个,末尾-1返回值实际读取的个数 114 | int read(char[] cbuf,int off, int len) //每次读取一组字符,最多len个,数据存入数组从off开始,末尾-1返回值实际读取的个数 115 | void close() 116 | 117 | - **FileWriter**继承自Writer 118 | 核心方法: 119 | 120 | 1、构造方法 121 | FileWriter(File file) 122 | FileWriter(File file, boolean append) 123 | FileWriter(String fileName) 124 | FileWriter(String fileName, boolean append) //构造方法来指定是否使用追加模式 125 | 2、成员方法 126 | void write(int c) 127 | void write(char[] cbuf,int off, int len) 128 | void write(String str, int off, int len) 129 | void flush() 130 | void close() 131 | 132 | ###内存流 133 | 134 | > 说明:内存流主要用来操作内存,输入和输出可以从文件中来,也可以将设置在内存之上(内存:相当于长度可变的字节数组) 135 | 136 | 分类: 137 | **ByteArrayInputStream**类:主要完成将内容从内存读入程序之中 138 | 139 | 数据<<<---------ByteArrayInputStream<<<---------内存 140 | 141 | 构造方法: 142 | 143 | ByteArrayInputStream(byte[] b) 144 | ByteArrayInputStream(byte[] b,int off,int len) 145 | 146 | 常用方法: 147 | 148 | read() 149 | skip() 150 | available() 151 | 152 | 153 | **ByteArrayOutputStream**类:主要是将数据写入到内存中 154 | 155 | 数据--------->>>ByteArrayOutputStream--------->>>内存 156 | 157 | 构造方法: 158 | 159 | ByteArrayOutputStream() 160 | ByteArrayOutputStream(int size) :指定缓冲区大小(byte) 161 | 162 | 常用方法: 163 | 164 | byte[] toByteArray():将内存流转换为字节数组 165 | toString() 166 | write(int) 167 | write(byte[] bytes) 168 | write(byte[] bytes ,int off,int len) 169 | writeTo(OutputStream) 170 | 171 | **注意:内存流不需要关闭** 172 | 173 | ##处理流(过滤流) 174 | ###缓冲流 175 | > 说明:缓冲流是处理流的一种,建立在相应的节点流之上,对读写的数据提供了缓冲的功能,提高了读写的效率,还增加了一些新的方法 176 | 177 | **注意**: 178 | - 1、对于缓冲输出流,写出的数据会先缓存在内存缓冲区中,关闭此流前要用flush()方法将缓存区的数据立刻写出 179 | - 2、关闭过滤流时,会自动关闭过滤流所包装的所有底层流 180 | 181 | **BufferedInputStream** 可以对任何的InputStream流进行包装 182 | 183 | **BufferedOutputStream** 可以对任何的OutputStream流进行包装 184 | 185 | **BufferedReader** 可以对任何的Reader流进行包装 186 | > 新增了readLine()方法用于一次读取一行字符串(以‘\r’或‘\n’认为一行结束)返回一行 如果没有返回null 187 | 188 | 189 | **BufferedWriter** 可以对任何的Writer流进行包装 190 | > 新增了newLine()方法,用于跨平台的写入换行符 191 | 192 | 193 | ###Object流 194 | >说明:JDK提供的ObjectOutputStream和ObjectInputStream类是用于存储和读取基本数据类型或对象的过滤流 195 | 196 | **序列化**:用ObjectOutputStream类保存基本数据类型或对象的机制叫序列化 197 | 198 | **反序列化**:用ObjectInputStream类读取基本数据类型或对象的机制叫反序列化 199 | 200 | **Serializable接口** 201 | 202 | 作用:能被序列化的对象所对应的类必须实现java.io.Serializable这个标识性接口 203 | 注意:实现此接口的类,需要提供一个静态long类型的常量serialVersionUID,保证序列化与反序列化的一致性 204 | 205 | **构造方法**: 206 | 207 | public ObjectOutputStream(OutputStream out) 208 | public ObjectInputStream(InputStream in) 209 | 210 | **transient关键字**: 211 | 212 | transient关键字修饰成员变量时,表示这个成员变量是不需要序列化的 213 | static修饰的成员变量也不会被序列化 214 | 215 | 216 | ###打印流 217 | > 说明:向控制台输出数据 218 | 219 | PrintStream类:字节输出流 220 | 221 | PrintWriter类:字符输出流 222 | 223 | 打印流示例(**注意:write写入的是字节**): 224 | 225 | PrintStream ps = new PrintStream("src/print.txt"); 226 | ps.write(355);// 字节 00000000 00000000 00000001 01100011 227 | // 舍弃前三位---》01100011--》c 228 | ps.println(355); 229 | ps.flush(); 230 | ps.close(); 231 | 232 | 233 | **注意** 234 | 235 | System.out就是PrintStream的一个实例 236 | PrintStream和PrintWriter的输出操作不会抛出异常 237 | 238 | 构造方法: 239 | 240 | PrintStream(OutputStream out) 241 | PrintStream(OutputStream out, boolean autoFlush) 242 | PrintWriter(Writer out) 243 | PrintWriter(Writer out, boolean autoFlush) 244 | PrintWriter(OutputStream out) 245 | PrintWriter(OutputStream out, boolean autoFlush) 246 | 247 | ###转换流 248 | > 作用:转换流用于在字节流和字符流之间转换。 249 | 250 | 分类: 251 | 252 | - **InputStreamReader**类 253 | 254 | 1)是Reader的子类,将输入的字节流变为字符流,即将一个字节流的输入对象变为字符流的输入对象 255 | 2)InputStreamReader需要和InputStream“套接”,它可以将字节流中读入的字节解码成字符 256 | 257 | - **OutputStreamWriter**类 258 | 259 | 1)是Writer的子类,将输出的字符流变为字节流,即将一个字符流的输出对象变为字节流的输出对象 260 | 2)OutputStreamWriter需要和OutputStream“套接”,它可以将要写入字节流的字符编码成字节 261 | 262 | 转换过程: 263 | - 写入数据 264 | 265 | 程序--->>字符数据--->>字符流--->>OutputStreamWriter--->>字节流--->>文件 266 | 267 | - 读出数据 268 | 269 | 程序<<---字符数据<<---字符流<<----InputStreamReader<<---字节流<<---文件 270 | 271 | ###数据流 272 | 273 | 274 | **DataInputStream**类 275 | > 作用:读取简单数据类型和字符串 276 | 277 | 核心方法: 278 | 279 | readInt() 读取一个基本数据类型数据 280 | readInt() 读取一个基本数据类型数据 281 | 282 | **DataOutputStream**类 283 | > 作用:写出简单数据类型和字符串 284 | 285 | 核心方法: 286 | 287 | writeInt(int i) 288 | writeUTF(String s) 写入UTF-8编码的字符串 289 | 290 | ##RandomAccessFile类(随机访问文件) 291 | > 作用:完成随机读取功能,可以读取指定位置的内容 292 | 293 | 构造方法: 294 | 295 | public RandomAccessFile(File file, String mode) 296 | public RandomAccessFile(File file, String mode) 297 | 298 | 文件的打开模式 299 | 300 | “r” 以只读方式打开。调用结果对象的任何 write 方法都将导致抛出 IOException。 301 | “rw” 打开以便读取和写入。如果该文件尚不存在,则尝试创建该文件。 302 | 303 | 常用方法: 304 | 305 | getFilePointer():返回子文件中当前的偏移量 306 | seek(long l):设置到此文件开头测量到的文件的偏移量 在该位置的下一个发生读、写操作 307 | 308 | 注意: 309 | 310 | RandomAccessFile raf = new RandomAccessFile("src/per.txt", "rw"); 311 | //这里遍历的时候需注意要用getFilePointer()读取光标的位置 312 | for (int i = 0; i < raf.length(); i = (int) raf.getFilePointer()) { 313 | //do ... 314 | } -------------------------------------------------------------------------------- /IO流和文件的相关练习.md: -------------------------------------------------------------------------------- 1 | ##三种复制方式的对比: 2 | 3 | 直接一个字节一个字节拷贝: 4 | 5 | // 一个字节一个字节复制:一滴一滴转移 6 | static void copyBybyte(FileInputStream fis, FileOutputStream fos) 7 | throws IOException { 8 | int b = 0; 9 | long start = System.currentTimeMillis(); 10 | while ((b = fis.read()) != -1) { 11 | fos.write(b); 12 | } 13 | long end = System.currentTimeMillis(); 14 | System.out.println("一个字节一个字节复制成功,共花费" + (end - start) + "ms"); 15 | 16 | } 17 | 18 | 通过数组拷贝: 19 | 20 | // 先将数据放入数组中复制:一瓢一瓢转移 21 | static void copyByBytes(FileInputStream fis, FileOutputStream fos) 22 | throws IOException { 23 | byte[] b = new byte[512]; 24 | int len = 0; 25 | long start = System.currentTimeMillis(); 26 | while ((len = fis.read(b)) != -1) { 27 | fos.write(b, 0, len); // 读取多少写多少 28 | } 29 | long end = System.currentTimeMillis(); 30 | System.out.println("放入数组复制,共花费" + (end - start) + "ms"); 31 | } 32 | 33 | 通过缓冲区拷贝: 34 | 35 | // 放入缓冲区中赋值:一桶一桶转移 36 | static void copyByBuffer(FileInputStream fis, FileOutputStream fos) 37 | throws IOException { 38 | // 创建缓冲区对象 39 | BufferedInputStream bis = null; 40 | BufferedOutputStream bos = null; 41 | try { 42 | bis = new BufferedInputStream(fis); 43 | bos = new BufferedOutputStream(fos); 44 | 45 | byte[] b = new byte[512]; 46 | int len = 0; 47 | long start = System.currentTimeMillis(); 48 | while ((len = bis.read(b)) != -1) { 49 | bos.write(b, 0, len); // 读取多少写多少 50 | } 51 | long end = System.currentTimeMillis(); 52 | System.out.println("放入数组复制,共花费" + (end - start) + "ms"); 53 | } finally { 54 | if (bis != null) { 55 | bis.close(); 56 | } 57 | if (bos != null) { 58 | bos.close(); 59 | } 60 | } 61 | } 62 | 63 | 通过以上三种方式的对比得出:**对于大文件的拷贝使用缓冲区的复制效率最高,建议使用** 64 | 65 | ##File相关 66 | 列出指定目录下的文件及其文件夹,包括子目录中的内容 67 | 68 | public static void listFiles(File file) { 69 | File[] files = file.listFiles(); // 获得当前目录下所有的目录和文件 70 | for (File f : files) { 71 | System.out.println(f.getName()); //放到这里会打印目录和文件 72 | if (f.isDirectory()) {// 如果是一个目录 73 | listFiles(f); //递归调用 74 | } 75 | } 76 | } 77 | 78 | 第二种方法(对错误规避比较规范,只打印文件,不打印目录): 79 | 80 | public static void listDirectory(File dir) throws IOException{ 81 | if (!dir.exists()){ 82 | throw new IllegalArgumentException("目录:"+dir+"不存在"); 83 | } 84 | if (!dir.isDirectory()){ 85 | throw new IllegalArgumentException(dir+"不是目录"); 86 | } 87 | File[] files = dir.listFiles(); 88 | if (files!=null && files.length>0){ 89 | for(File file : files){ 90 | if (file.isDirectory()){ 91 | listDirectory(file); 92 | }else { 93 | System.out.println(file); //这里只打印文件,而不打印目录 94 | } 95 | } 96 | } 97 | } 98 | 99 | --- 100 | ###合并文件 101 | 102 | public static void main(String[] args) throws IOException { 103 | InputStream is1 = new FileInputStream( 104 | "src/com/perperties/Demo9.java"); 105 | InputStream is2 = new FileInputStream( 106 | "src/com/perperties/Demo10.java"); 107 | InputStream is3 = new FileInputStream( 108 | "src/com/perperties/Demo11.java"); 109 | ArrayList list = new ArrayList(); 110 | list.add(is1); 111 | list.add(is2); 112 | list.add(is3); 113 | 114 | SequenceInputStream sis = new SequenceInputStream( 115 | Collections.enumeration(list)); 116 | // 包装字节流到缓冲区字符流(转换流) 117 | BufferedReader br = new BufferedReader(new InputStreamReader(sis)); 118 | // 创建输出流,读取合并流,保存到文件中 119 | BufferedWriter bw = new BufferedWriter(new FileWriter("src/demo.txt")); 120 | String line = null; 121 | while ((line = br.readLine()) != null) { 122 | bw.write(line); 123 | bw.newLine(); 124 | } 125 | bw.flush(); 126 | br.close(); 127 | bw.close(); 128 | System.out.println("合并成功!!"); 129 | } 130 | 131 | ###文件分割 132 | 133 | public class Demo { 134 | // 将一个文件分割为指定大小的文件 135 | // 1)定义一个固定大小的字节数组 136 | // 2)目标位置、名称 137 | // 3) 循环读取固定大小的字节,然后写到目标位置 138 | 139 | public static void main(String[] args) throws IOException { 140 | File f = new File("src/1.jpg"); 141 | InputStream is = new FileInputStream(f); 142 | byte[] bytes = new byte[1024 * 1024];// 1M 143 | int len = 0; 144 | int index = 0; 145 | while ((len = is.read(bytes)) != -1) { 146 | FileOutputStream fos = new FileOutputStream(new File("images", 147 | (index++) + f.getName())); 148 | fos.write(bytes, 0, len); 149 | 150 | } 151 | is.close(); 152 | 153 | } 154 | } 155 | 156 | ###Properties操作 157 | 158 | // 只能登录3次,3次试用 159 | static void login() throws IOException { 160 | File file = new File("src/count.properties"); 161 | if (!file.exists()) { 162 | file.createNewFile(); 163 | } 164 | Properties ps = new Properties(); 165 | ps.load(new FileInputStream(file)); 166 | // 获得count的值,并给count赋初值 167 | String count = ps.getProperty("count", "0"); 168 | int i = Integer.parseInt(count); 169 | if (i < 3) { 170 | i++; 171 | ps.setProperty("count", i + "");// 更新属性 172 | // 保存本次更新的属性值 173 | ps.store(new FileOutputStream(file), ""); 174 | 175 | } else { 176 | System.err.println("已经试用超过3次"); 177 | System.exit(0); 178 | } 179 | 180 | } 181 | 182 | -------------------------------------------------------------------------------- /SQL.md: -------------------------------------------------------------------------------- 1 | #SQL 结构化的查询语言 Structured Query Language 2 | 3 | ------------ 4 | ###分类 5 | - DDL 数据定义语言: `create 、drop 、 alter` 6 | - DML:数据操作语言: `CURD:增删改查` 7 | - DCL:数据控制语言 8 | - 数据查询语言(DQL:Data Query Language) 9 | - 指针控制语言(CCL) 10 | - 事务处理语言(TPL) 11 | 12 | -------------- 13 | ##SQLite常用语法(只记录SQLite独特的部分) 14 | 15 | **sqlite: 以`.`开头以`;`结尾** 16 | 17 | sqlite>.help //输出帮助信息 18 | sqlite>.open xxx.db //创建数据库 19 | sqlite>.header on //显示标题 20 | sqlite>.mode column //设置显示模式(默认为list,设置为column,其他模式可通过.help查看mode相关内容) 21 | 退出sqlite终端命令: 22 | sqlite>.quit 23 | 或 24 | sqlite>.exit 25 | sqlite>.show //列出当前显示格式的配置: 26 | sqlite>.schema table_name //查看指定表的创建语句 27 | sqlite>.schema //查看所有表的创建语句 28 | sqlite>.database //查看数据库文件信息命令 29 | sqlite>.dump table_name //以sql语句的形式列出表内容 30 | sqlite>.separator symble //设置显示信息的分隔符 31 | sqlite>.width width_value //设置每一列的显示宽度 32 | 33 | 34 | **在SQLite中需要注意**: 35 | 设置外键约束之后要启用外键约束(启用之前插入的不合法的数据,是被允许的,所以要谨慎,这可能是一个bug) 36 | 37 | 启用外键语法: 38 | 39 | pragma foreign_keys=on; 40 | 41 | **SQLite支持哪些数据类型** 42 | 43 | NULL 值为NULL 44 | INTEGER 值为带符号的整型,根据类别用1,2,3,4,6,8字节存储 45 | REAL 值为浮点型,8字节存储 46 | TEXT 值为text字符串,使用数据库编码(UTF-8, UTF-16BE or UTF-16-LE)存储 47 | BLOB 值为二进制数据,具体看实际输入 48 | 49 | 但实际上,sqlite3也接受如下的数据类型: 50 | smallint 16 位元的整数 51 | interger 32 位元的整数 52 | decimal(p,s) p 精确值和 s 大小的十进位整数,精确值p是指全部有几个数(digits)大小值 ,s是指小数点後有几位数。如果没有特别指定,则系统会设为 p=5; s=0 。 53 | float 32位元的实数。 54 | double 64位元的实数。 55 | char(n) n 长度的字串,n不能超过 254。 56 | varchar(n) 长度不固定且其最大长度为 n 的字串,n不能超过 4000。 57 | graphic(n) 和 char(n) 一样,不过其单位是两个字元 double-bytes, n不能超过127。这个形态是为了支援两个字元长度的字体,例如中文字。 58 | vargraphic(n) 可变长度且其最大长度为 n 的双字元字串,n不能超过 2000。 59 | date 包含了 年份、月份、日期。 60 | time 包含了 小时、分钟、秒。 61 | timestamp 包含了 年、月、日、时、分、秒、千分之一秒。 62 | 63 | 实际上:SQLite是无类型的. 这意味着你可以保存任何类型的数据到你所想要保存的任何表的任何列中, 64 | 无论这列声明的数据类型是什么(只有自动递增Integer Primary Key才有用). 对于SQLite来说对字段不指定类型是完全有效的. 65 | 66 | -------------- 67 | ##SQL语法 68 | ###创建表以及增、删、改、查 69 | 70 | create table 表名( 71 | 字段名 数据类型 说明 , 72 | ... ... ... , 73 | ... ... ... 74 | ); 75 | 76 | 外键约束: 77 | 78 | 字段名 references 主表(主键) 79 | 80 | 示例: 81 | 82 | create table user( 83 | uid int primary key auto_increment, //主键自增 84 | uname varchar(40) UNIQUE NOT NULL, //唯一且不为空 85 | password varchar(40), 86 | email varchar(60), 87 | phone varchar(20) UNIQUE NOT NULL, 88 | balance int(10) NOT NULL DEFAULT 999,//不不空且默认值是999 89 | ); 90 | 91 | 外键约束示例: 92 | 93 | create table type( 94 | tid Integer primary key autoincrement, //注意把autoincrement写到后面,放到前面可能会不起作用 并且只能用Integer类型(在SQLite中) 95 | tname varchar(20) 96 | ); 97 | 98 | create table goods( 99 | id Integer primary key autoincrement, 100 | name varchar(20) not null, 101 | num int check(name>=0), //check约束 102 | price int, 103 | address varchar(50), 104 | tid references type(tid) //外键约束:goods表中的tid字段依赖于type表中的tid字段 105 | ) 106 | 107 | 108 | 约束条件: 109 | 110 | 主键约束:primary key 111 | 外键约束:foreigh key 112 | 唯一约束:unique 113 | 检查约束:check(表达式) 114 | 默认约束:default(默认值) 115 | 非空约束:not null 116 | 117 | 118 | 增删改查语法: 119 | 120 | C(Create 增加): 121 | insert into 表名 (字段名) values(值)[,(值),(值)] 122 | R(Retrieve 查询) 123 | select 字段名 from 表名 124 | [where 条件] 125 | [group by 分组条件] 126 | [having 筛选条件] 127 | [order by 排序字段[asc|desc]] 128 | [limit n] 129 | limit 2 前两位 130 | limit 3,4 跳过3条后的再显示4条 131 | U(Update 修改) 132 | update 表名 set 字段=值[,字段=值] [where 条件] 133 | D(Delete 删除) 134 | delete from 表名[where 条件] 135 | 136 | 137 | where 条件: 138 | `>`、 `< `、 `=` 、`!=` 、`>=` 、`<=` 、`<> (注:不等于)` 139 | 140 | `not` `and` `or` 141 | 142 | `in(值,值,值)` 143 | 144 | `between ... and ...` 145 | 146 | 模糊查询: 147 | `%` **:任意多个字符** 148 | `_` ** : 任意一个字符** 149 | 150 | ###表链接 151 | **注:能用链接查询尽量不要用嵌套子查询(效率问题)** 152 | 153 | 分类: 154 | 155 | 内连接:两张表中同时存在的记录 156 | inner join //可以简写成 join 157 | 外连接: 158 | 左外连接:以A表作为主表,主表的信息会全部显示,如果B表有对应的数据显示数据,否则显示null 159 | A left join B 160 | 161 | 右外连接:A right join B <=等价于=> B left join A //(sqlite不支持) 162 | 全连接:A full join B <=等价于=> 左外+右外 //(sqlite不支持) 163 | 164 | 语法: 165 | 166 | select 字段 167 | from 表名1 join 表名2 168 | on 表1.键 = 表2.键 169 | 170 | 扩展:自链接(自己连接自己) 171 | 示例: 172 | 173 | type表: 174 | id tname pid 175 | 1 食品 0 176 | 2 饼干 1 177 | 3 饮料 1 178 | 4 可乐 3 179 | 5 可口可乐 4 180 | 6 百事 4 181 | 7 家电 0 182 | 8 冰箱 7 183 | 184 | 需要解决的问题 185 | 现要求查询显示如下: 186 | 187 | 编号 类别名称 父类名称 188 | 2 饼干 食品 189 | 3 饮料 食品 190 | 4 可乐 饮料 191 | 5 可口可乐 可乐 192 | 6 百事 可乐 193 | 8 冰箱 家电 194 | 195 | 解决(使用自链接) 196 | 查询语句如下: 197 | 198 | select a.id as 编号 a.tname as 类别名称 ,b.tname as 父类名称 199 | from type as a join type as b 200 | on a.pid = b.id 201 | 202 | ###查询语句练习 203 | 现有如下表: 204 | 205 | sqlite> select * from goods; 206 | id name num address tid 207 | ---------- ---------- ---------- ---------- ---------- 208 | 1 bb 20 beijing 1 209 | 2 asdf 40 beijing 2 210 | 3 nljksdff 40 shanghai 2 211 | 4 sdff 100 shanghai 1 212 | 213 | sqlite> select * from type; 214 | tid tname 215 | ---------- ---------- 216 | 1 玩具 217 | 2 服装 218 | 3 饮料 219 | 220 | 查询: 221 | 222 | //按照address分组,并显示各组的总数(条目) 223 | sqlite> select address,count(*) from goods group by address; 224 | 225 | address count(*) 226 | ---------- ---------- 227 | beijing 2 228 | shanghai 2 229 | 230 | //按照address分组,查询各地的产品数量和总量 231 | sqlite> select address,count(*) as 产品数量,sum(num) as 总量 from goods g 232 | address; 233 | 234 | address 产品数量 总量 235 | ---------- ---------- ---------- 236 | beijing 2 60 237 | shanghai 2 140 238 | 239 | //按照address分组,查询各地的产品数量和总量,并筛选总量大于100的 240 | sqlite> select address,count(*) as 产品数量,sum(num) as 总量 from goods g 241 | address having sum(num)>100; 242 | 243 | address 产品数量 总量 244 | ---------- ---------- ---------- 245 | shanghai 2 140 246 | 247 | //按照产品数量降序排列,并取得前两条数据 248 | sqlite> select * from goods order by num desc limit 2; 249 | 250 | id name num address tid 251 | ---------- ---------- ---------- ---------- ---------- 252 | 4 sdff 100 shanghai 1 253 | 2 asdf 40 beijing 2 254 | 255 | //按照产品数量降序排列,并跳过结果集中的第一条数据,再显示两条数据 256 | sqlite> select * from goods order by num desc limit 1,2; 257 | 258 | id name num address tid 259 | ---------- ---------- ---------- ---------- ---------- 260 | 2 asdf 40 beijing 2 261 | 3 nljksdff 40 shanghai 2 262 | 263 | //查询商品地址在'beijing'或'shanghai'中的商品信息 264 | sqlite> select * from goods where address in('beijing','shanghai'); 265 | 266 | id name num address tid 267 | ---------- ---------- ---------- ---------- ---------- 268 | 1 bb 20 beijing 1 269 | 2 asdf 40 beijing 2 270 | 3 nljksdff 40 shanghai 2 271 | 4 sdff 100 shanghai 1 272 | 273 | //查询商品表中商品数量最大的商品信息 274 | sqlite> select * from goods where num = (select max(num) from goods); 275 | id name num address tid 276 | ---------- ---------- ---------- ---------- ---------- 277 | 4 sdff 100 shanghai 1 278 | 279 | //查询goods表中name中包含f的所有商品类别信息 280 | sqlite> select * from type where tid in(select tid from goods where name like %f%'); 281 | 282 | tid tname 283 | ---------- ---------- 284 | 1 玩具 285 | 2 服装 286 | 287 | //查询goods中不存在的商品类别信息 288 | sqlite> select * from type where tid not in(select tid from goods); 289 | 290 | tid tname 291 | ---------- ---------- 292 | 3 饮料 293 | 294 | //先按照tid对goods分组,计算各组的num的平均值,列出平均值小于100的tid 295 | sqlite> select tid from goods group by tid having avg(num)<100; 296 | 297 | tid 298 | ---------- 299 | 1 300 | 2 301 | 302 | //先按照tid对goods分组,计算各组的num的平均值,获取平均值小于100的tid并显示其类别信息 303 | sqlite> select * from type where tid in (select tid from goods group by tid having avg(num)<100); 304 | 305 | tid tname 306 | ---------- ---------- 307 | 1 玩具 308 | 2 服装 309 | 310 | //goods与type 内链接 311 | sqlite> select type.*,goods.* from type join goods on type.tid = goods.tid; 312 | 313 | tid tname id name num address tid 314 | 315 | ---------- ---------- ---------- ---------- ---------- ---------- - 316 | -- 317 | 1 玩具 1 bb 20 beijing 1 318 | 319 | 2 服装 2 asdf 40 beijing 2 320 | 321 | 2 服装 3 nljksdff 40 shanghai 2 322 | 323 | 1 玩具 4 sdff 100 shanghai 1 324 | 325 | //goods与type 内链接 326 | sqlite> select goods.*,tname from type join goods on type.tid = goods.tid; 327 | 328 | id name num address tid tname 329 | ---------- ---------- ---------- ---------- ---------- ---------- 330 | 1 bb 20 beijing 1 玩具 331 | 2 asdf 40 beijing 2 服装 332 | 3 nljksdff 40 shanghai 2 服装 333 | 4 sdff 100 shanghai 1 玩具 334 | 335 | //type与goods 左链接 336 | sqlite> select goods.*,tname from type left join goods on type.tid = goods.tid; 337 | 338 | id name num address tid tname 339 | ---------- ---------- ---------- ---------- ---------- ---------- 340 | 1 bb 20 beijing 1 玩具 341 | 4 sdff 100 shanghai 1 玩具 342 | 2 asdf 40 beijing 2 服装 343 | 3 nljksdff 40 shanghai 2 服装 344 | 饮料 345 | //goods与type 左链接 相当于 type与goods 右链接 346 | sqlite> select goods.*,tname from goods left join type on type.tid = goods.tid; 347 | 348 | id name num address tid tname 349 | ---------- ---------- ---------- ---------- ---------- ---------- 350 | 1 bb 20 beijing 1 玩具 351 | 2 asdf 40 beijing 2 服装 352 | 3 nljksdff 40 shanghai 2 服装 353 | 4 sdff 100 shanghai 1 玩具 354 | 355 | //自链接(这个没啥意义) 356 | sqlite> select a.*,b.* from type as a join type as b on a.tid = b.tid; 357 | 358 | tid tname tid tname 359 | ---------- ---------- ---------- ---------- 360 | 1 玩具 1 玩具 361 | 2 服装 2 服装 362 | 3 饮料 3 饮料 363 | 364 | 365 | 查询男女的人数 366 | Select sex,count(*) 367 | From student 368 | Group by sex; 369 | 男同学的平均年龄比女同学的平均年龄大几岁? 370 | select (select avg(age) from student where sex = '男')-(select avg(age) 371 | from student where sex='女') as 最美年龄差; 372 | 373 | 查询和学号是2的同名的同学 374 | Select * from student 375 | Where name=(select name from student where id=2) 376 | 377 | 查询年龄第二大的女生 378 | Select * from student where sex = ‘女’ and age=(select max(age) from student 379 | Where age <(select max(age) from student) 380 | ) 381 | 382 | 查询年龄最大的同学 383 | Select * from student order by age desc limit 1; 384 | 该sql语句不能把所有年龄最大的同学全部包含,如果最大的年龄的同学不唯一 385 | Select * from student where age =(select max(age) from student) 386 | 387 | Select * from stduent where age=(select age from student order by age desc limit 1) 388 | 389 | 查询年龄最大的男女同学 390 | Select max(age) from student group by sex 391 | 392 | 男女最大年龄差 393 | Select ((select max(age)from student where sex=’男’)-(select min(age) from student where sex=’女’)) as 最大年龄差 394 | 395 | 396 | 397 | --------------- 398 | -------------------------------------------------------------------------------- /Socket.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wswenyue/note/a7df9fc77f72331270f228576a056501c0d06ba6/Socket.md -------------------------------------------------------------------------------- /_Footer.md: -------------------------------------------------------------------------------- 1 |
**Love DuoQing love life**
2 | 3 | 4 | 5 | ©wswenyue -------------------------------------------------------------------------------- /_Sidebar.md: -------------------------------------------------------------------------------- 1 | **越努力,越幸运** 2 | 3 | ------------------- 4 | 5 | [我的简书笔记](http://www.jianshu.com/users/ac745f130921/latest_articles "我的简书笔记") 6 | 7 | [我的麦库分享](https://note.sdo.com/u/635033639628438451 "我的麦库分享") 8 | 9 | [我的微博](http://weibo.com/wswenyue "我的微博") 10 | 11 | ------ 12 | 13 | >梦想还是要有的 14 | 15 | -------------------------------------------------------------------------------- /android工具包/图片的加载与显示.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wswenyue/note/a7df9fc77f72331270f228576a056501c0d06ba6/android工具包/图片的加载与显示.md -------------------------------------------------------------------------------- /handler.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wswenyue/note/a7df9fc77f72331270f228576a056501c0d06ba6/handler.png -------------------------------------------------------------------------------- /issue/多线程相关.md: -------------------------------------------------------------------------------- 1 | ##HashMap并发修改读取异常---java.util.ConcurrentModificationExceptio 2 | 3 | Map map = new HashMap<>(); 4 | 5 | for (Map.Entry entry : map.entrySet()) { 6 | //对entry进行处理 7 | } 8 | 9 | 或者 10 | 11 | Iterator it = map.entrySet().iterator(); 12 | while (it.hasNext()) 13 | { 14 | Entry item = it.next(); 15 | map.remove(item.getKey()); 16 | } 17 | 18 | **上面这两种方法都会造成java.util.ConcurrentModificationExceptio异常** 19 | 20 | 解决方法: 21 | 22 | Iterator it = map.entrySet().iterator(); 23 | while (it.hasNext()) 24 | { 25 | Entry item = it.next(); 26 | it.remove(); 27 | } 28 | 29 | 总结:**遍历读写操作要用 Iterator 迭代器的方法** 30 | **对于多线程,高并发尽量不要使用HashMap,要使用ConcurrentHashMap来替代** 31 | 32 | 问题产生的原因: 33 | 34 | 引用于网络: 35 | >当使用 fail-fast iterator 对 Collection 或 Map 进行迭代操作过程中尝试直接修改 Collection / Map 的内容时,即使是在单线程下运行, java.util.ConcurrentModificationException 异常也将被抛出。 36 | 37 | Iterator 是工作在一个独立的线程中,并且拥有一个 mutex 锁。 Iterator 被创建之后会建立一个指向原来对象的单链索引表,当原来的对象数量发生变化时,这个索引表的内容不会同步改变,所以当索引指针往后移动的时候就找不到要迭代的对象,所以按照 fail-fast 原则 Iterator 会马上抛出 java.util.ConcurrentModificationException 异常。 38 | 39 | 所以 Iterator 在工作的时候是不允许被迭代的对象被改变的。但你可以使用 Iterator 本身的方法 remove() 来删除对象, Iterator.remove() 方法会在删除当前迭代对象的同时维护索引的一致性。 40 | 41 | 有意思的是如果你的 Collection / Map 对象实际只有一个元素的时候, ConcurrentModificationException 异常并不会被抛出。这也就是为什么在 javadoc 里面指出: it would be wrong to write a program that depended on this exception for its correctness: ConcurrentModificationException should be used only to detect bugs. 42 | 43 | 附:来自ibm developerworks上对java.util.concurrent包的说明片段: 44 | >java.util 包中的集合类都返回 fail-fast 迭代器,这意味着它们假设线程在集合内容中进行迭代时,集合不会更改它的内容。如果 fail-fast 迭代器检测到在迭代过程中进行了更改操作,那么它会抛出 ConcurrentModificationException ,这是不可控异常。 45 | 在迭代过程中不更改集合的要求通常会对许多并发应用程序造成不便。相反,比较好的是它允许并发修改并确保迭代器只要进行合理操作,就可以提供集合的一致视图,如 java.util.concurrent 集合类中的迭代器所做的那样。 46 | java.util.concurrent 集合返回的迭代器称为弱一致的(weakly consistent) 迭代器。对于这些类,如果元素自从迭代开始已经删除,且尚未由 next() 方法返回,那么它将不返回到调用者。如果元素自迭代开始已经添加,那么它可能返回调用者,也可能不返回。在一次迭代中,无论如何更改底层集合,元素不会被 返回两次。 -------------------------------------------------------------------------------- /issue/获取屏幕相关高度.md: -------------------------------------------------------------------------------- 1 | #窗口的几个区域如下图所示: 2 | 3 | ![](http://7xj2yt.com1.z0.glb.clouddn.com/android_窗口.png) 4 | 5 | #获取除状态栏,标题栏之外的文本区域的高度,也就是正文区域高度(黄色边框区域) 6 | 7 | ```java 8 | @Override 9 | public void onWindowFocusChanged(boolean hasFocus) { 10 | super.onWindowFocusChanged(hasFocus); 11 | View windows = getWindow().findViewById(Window.ID_ANDROID_CONTENT);///获得根视图 12 | int height = windows.getHeight();//这个高度就是正文区域高度 13 | 14 | if (hasFocus) { 15 | //TODO 当Activity获取到焦点的时候执行其他任务 16 | } 17 | } 18 | ``` 19 | 20 | 注: 21 | 为什么要在这个方法获取,因为在Activity的生命周期方法里获取不到,获取的全是0 22 | 23 | 24 | > Activity生命周期中,onStart, onResume, onCreate都不是真正visible的时间点,真正的visible时间点是onWindowFocusChanged()函数被执行时。[参考博文](http://www.cnblogs.com/lijunamneg/archive/2013/01/19/2867532.html) 25 | 26 | 相关方法的执行顺序: 27 | 28 | ``` 29 | 1: entry: onStart---->onResume---->onAttachedToWindow----------->onWindowVisibilityChanged--visibility=0---------->onWindowFocusChanged(true)-------> 30 | 31 | 2. exit: onPause---->onStop---->onWindowFocusChanged(false) ---------------------- (lockscreen) 32 | 33 | 3. exit : onPause----->onWindowFocusChanged(false)-------->onWindowVisibilityChanged--visibility=8------------>onStop(to another activity) 34 | 35 | ``` -------------------------------------------------------------------------------- /issue/获取视图控件的宽高.md: -------------------------------------------------------------------------------- 1 | #获取视图控件的宽高 2 | 以高度为例: 3 | 4 | ##获取高度有两种方法: 5 | getHeight()或getMeasuredHeight() 6 | **如果直接获取,那么有时候获得的结果为0**,这是因为调用时视图还没有装载好,或者还没有测量完成,系统中通过xml装载视图的的方法一般都是异步的方法。 7 | 为了解决这个问题可以使用下面的策略,**建议使用getMeasuredHeight()这个方法** 8 | ###getHeight() 9 | getHeight():必须在onLayout方法执行完后,才能获取到宽高 10 | 一般获取的时候只能通过设置监听,来监听onLayout方法执行完来获取 11 | 代码示例: 12 | 13 | ```java 14 | //给要获取宽高的view添加事件监听 15 | view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { 16 | @Override 17 | public void onGlobalLayout() { 18 | //我们只是获取一次的宽高,所有获取之后要将该监听移除 19 | //如果不移除,每次视图重绘都会调用。影响性能 20 | view.getViewTreeObserver().removeGlobalOnLayoutListener(this); 21 | int height = view.getHeight();//这里可以直接获取 22 | } 23 | }); 24 | 25 | ``` 26 | 27 | 也可以通过添加如下方法的监听来获取 28 | 29 | ```java 30 | view.getViewTreeObserver().addOnPreDrawListener(new OnPreDrawListener() 31 | { 32 | @Override 33 | public boolean onPreDraw() 34 | { 35 | view.getViewTreeObserver().removeOnPreDrawListener(this); 36 | System.out.println("onPreDraw width=" + view.getWidth() + " height=" + view.getHeight()); 37 | return true; 38 | } 39 | }); 40 | 41 | ``` 42 | 43 | 也可以onWindowFocusChanged回调方法中获取 44 | [可以参考笔记:获取屏幕相关高度](./获取屏幕相关高度) 45 | 46 | ```java 47 | @Override 48 | public void onWindowFocusChanged(boolean hasFocus) 49 | { 50 | super.onWindowFocusChanged(hasFocus); 51 | if (hasFocus) 52 | { 53 | System.out.println("onWindowFocusChanged width=" + view.getWidth() + " height=" + view.getHeight()); 54 | } 55 | } 56 | ``` 57 | 58 | ###getMeasuredHeight() 59 | getMeasuredHeight():获取测量完的高度,只要在onMeasure方法执行完,就可以用它获取到宽高,在自定义控件内部多使用这个方法; 60 | **使用view.measure(0,0)方法可以主动通知系统去测量,然后就可以直接使用它获取宽高** 61 | 62 | 示例代码: 63 | 64 | ```java 65 | view.measure(0, 0);//主动通知系统去测量 66 | int height = view.getMeasuredHeight(); 67 | ``` -------------------------------------------------------------------------------- /issue/视图焦点问题.md: -------------------------------------------------------------------------------- 1 | ##与视图焦点相关的属性及方法 2 | ###对于视图 3 | 方法: 4 | 5 | 方法描述|在普通模式下|在触摸模式下 6 | -------|-----------|---------- 7 | 设置view接受焦点的资格|`setFocusable()`|`setFocusableInTouchMode()` 8 | 获取view是否有接受焦点的资格|`isFocusable()`|`isFocusableInTouchMode()` 9 | 请求获取焦点|`requestFocus()`|`requestFocusFromTouch()` 10 | 11 | 对应的xml属性: 12 | `android:focusable=""` true或false 13 | `android:focusableInTouchMode=""` true或false 14 | 15 | ###对于视图组控件 16 | 还有一个属性和方法用来控制焦点 17 | xml中的属性: 18 | 19 | ```xml 20 | android:descendantFocusability="" 21 | ``` 22 | 23 | 属性参数|意义 24 | -------|---- 25 | beforeDescendants| viewgroup会优先其子类控件而获取到焦点 26 | afterDescendants | viewgroup只有当其子类控件不需要获取焦点时才获取焦点 27 | blocksDescendants | viewgroup会覆盖子类控件而直接获得焦点即**禁止子控件获取焦点** 28 | 29 | 方法: 30 | 31 | ```java 32 | view.setDescendantFocusability() 33 | 参数:ViewGroup.FOCUS_AFTER_DESCENDANTS 34 | ViewGroup.FOCUS_BEFORE_DESCENDANTS 35 | ViewGroup.FOCUS_BLOCK_DESCENDANTS 36 | ``` 37 | 38 | 39 | ##对于上面的了解我们解决遇到的问题 40 | ###解决ListView中CheckBox抢焦点的问题 41 | 42 | **问题描述:** 43 | >ListView item中包含CheckBox、Button等之类(EditText除外,这个复杂点,在下面有解决),这些子控件默认有获取焦点的能力,视图组控件中如果包含有获取焦点能力的子控件,那么焦点会自动转移到该子控件上。并且由于每一个Window只拥有一个焦点,点击事件的触发,前提是该控件有焦点,所以视图组控件的点击将不会被触发。 44 | 45 | **解决方法:** 46 | 第一种方案: 47 | 给视图组控件设置属性: 48 | 49 | ```xml 50 | android:descendantFocusability="blocksDescendants" 51 | ``` 52 | 53 | 第二种方案: 54 | 给具有抢夺焦点能力的子控件设置属性: 55 | ```xml 56 | android:focusable="false" 57 | android:focusableInTouchMode="false" 58 | ``` 59 | 60 | ###解决ListView中EditText获取不到焦点的问题 61 | 为了使listView的点击事件和EditText的点击编辑输入都有效我们不能简单的设置EditText获取焦点等方法解决 62 | 需要在ListView的item选择事件中处理 63 | 64 | 首先在listView的xml文件中配置 65 | 66 | ```xml 67 | android:descendantFocusability="beforeDescendants" 68 | ``` 69 | 70 | 其次在监听事件中处理焦点: 71 | 72 | ```java 73 | listView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { 74 | @Override 75 | public void onItemSelected(AdapterView parent, View view, int position, long id) { 76 | //设置视图组ListView让出焦点 77 | listView.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS); 78 | EditText editText = (EditText) view.findViewById(R.id.cart_total_text); 79 | //EditText 请求获取焦点 80 | editText.requestFocus(); 81 | 82 | } 83 | 84 | @Override 85 | public void onNothingSelected(AdapterView parent) { 86 | //设置视图组ListView获取焦点 87 | listView.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS); 88 | } 89 | }); 90 | ``` 91 | -------------------------------------------------------------------------------- /javaBasic1.md: -------------------------------------------------------------------------------- 1 | ##听课笔记 2 | ####名词解释 3 | 4 | - JDK:java开发工具包 5 | - JRE:java运行时环境 6 | - JVM:java虚拟机 7 | 8 | ####java程序运行过程 9 | 10 | **`javac Demo01.java--->Demo01.class 字节码文件-->类加载器中-->运行java Demo01`** 11 | 12 | ####标识符、常量、变量 13 | 14 | 标识符:字母 数字 _ $ 组成,其中数字不能开头,不能是关键字。 15 | 类名:首字母大写 16 | 变量名和方法名:驼峰命名法 myname showinfo() addlist() 17 | 常量名:全部大写字母组成 18 | 包名:小写组成 域名倒置 com.baidu com.wenyue 19 | 常量:final 数据类型 常量名 = 值; 值不可以改变。 20 | 变量:可以改变 21 | 数据类型 变量名 = 值; 22 | 23 | 24 | 示例: 25 | 26 | final double PI; 27 | PI = 3.14; 28 | //PI = 3.23; //常量只能赋值一次 29 | int $c = 100; 30 | System.out.println("$c="+$c); 31 | //进制: 32 | int a = 010; 33 | System.out.println(a); 34 | int b = 0xa1; 35 | System.out.println(b); 36 | 37 | 38 | ####数据类型: 39 | 40 | 基本数据类型: 41 | 整型:byte(1字节 -128~127 Byte) short(2字节 -32768~32767 Short) int(4字节 -2147483648~2147483647 Integer) long(8字节 0L Long) 42 | 浮点型:float(4字节 Float 0.0f) double(8字节 Double) 43 | 字符型:char(2字节 Character) 44 | 布尔型:boolean (true false Boolen) 45 | 引用数据类型: 46 | 类 class 47 | 数组 array 48 | 接口 interface 49 | 50 | byte b1 = 10; 51 | //byte b2 = 200; 越界 52 | 53 | ####类型转换 54 | 55 | 数据类型转换: 56 | 自动类型转换:小--->大 57 | byte,short,char-->int-->long-->float-->double 58 | char可按照ASCII进行转换:a--》 97 A--》 65 0--》 48 59 | 强制类型转换:大--》 小 60 | (目标类型)变量 61 | 62 | 示例: 63 | 64 | int a = 100; 65 | byte b = (byte)a; 66 | byte b = 10; 67 | int a = 34; 68 | float f = 4.5f; 69 | short s = 45; 70 | double d = 10.5; 71 | double sum = b+a+f+s+d;//结果自动提升为double类型 72 | 73 | ####转义 74 | 75 | 转义:有格式的输出。通过\改变后面跟随的字符的含义 76 | \t:制表位 77 | \n:换行 78 | \\:斜杠 79 | \":双引号 80 | \r\n:回车换行 81 | 82 | #### 运算符 83 | 84 | - 逻辑运算符: &&(逻辑与) ||(逻辑或) !(逻辑非) & | ^ 异或 85 | 86 | a&&b(短路):如果a为false,则结果为false。b将不被判断 87 | a&b:如果a为false,结果为false。b会进行判断。a与b都会执行。 88 | a||b(短路):如果a为true,则结果为true。b将不被判断 89 | a|b:如果a为true,结果为true。b会进行判断。a与b都会执行。 90 | a^b:相同为false,不同为true。 91 | 92 | - 条件运算符: **三目运算符 ? :** 93 | 94 | > 条件表达式?语句1:语句2; //当表达式为true,结果为语句1,否则为语句2 95 | 96 | - 字符串连接符 + 97 | 98 | - 位运算符: &(按位与) |(按位或) ^(按位异或) ~(按位取反) >>(右移) <<(左移) >>>(无符号右移) 99 | 100 | 101 | - 进制转换: 102 | 103 | 十进制---》二进制 : 除2取余 10--》1010 104 | 二进制 --》十进制 :位权 * 符号^(n-1) 105 | (1010)二---->(0*2^0+1*2^1+0*2^2+1*2^3) =10 106 | 八进制---》二进制 107 | 1)通过十进制转换 108 | 2) 773 八--> 111 111 011 二 109 | 110 | 111 | 示例: 112 | 113 | int a = 4, b =3; 114 | int c = a++ + ++b + ++a; // c = 4 + 4 + 6 115 | int d = --b + ++a/2 - b++%2; // d = 3 + 7/2 – 3%2 116 | System.out.println("a=" + a + ",b=" + b + ",c=" + c + ",d=" + d); //a=7; b=4; c=10; d=5 117 | 118 | 119 | 位运算示例: 120 | 121 | System.out.println(5&3); //1 122 | System.out.println(5|3); //7 123 | System.out.println(5^3); //6 124 | 5 : 0000 0101 125 | 3 : 0000 0011 126 | 127 | 0101 128 | & 0011 129 | 0001 //1 130 | 131 | 0101 132 | | 0011 133 | 0111 //7 134 | 135 | 0101 136 | ^ 0011 137 | 0110 //6 138 | System.out.println(~5); 139 | /* 140 | ~5 = -6 141 | 0000 0101 142 | 1111 1010 (取反)--> -1 1111 1001 -->取反 0000 0110 143 | 每一位数取反,0即为1,1即为0. 144 | 如果出现负数,就按照负数的方式进行转换 145 | 如果正数取反,+1 ,得到真实的数 146 | 147 | 正数:原码 --》3 11 148 | 负数: -3 149 | 原码: 0000 0011 150 | 反码: 1111 1100 151 | +1 1111 1101 152 | */ 153 | //二进制输出使用:Integer.toBinaryString() 154 | System.out.println(Integer.toBinaryString(10)); 155 | System.out.println(Integer.toBinaryString(-5)); 156 | /* 157 | -5: 158 | 5的原码: 0000 0101 159 | 5的补码: 1111 1010 160 | +1: 1111 1011 161 | 负数的二进制 就是正数的补码+1 162 | 163 | 9二进制:0000 0000 0000 0000 0000 0000 0000 1001 164 | -9二进制: 165 | 9 原码:0000 0000 0000 0000 0000 0000 0000 1001 166 | 9 反码:1111 1111 1111 1111 1111 1111 1111 0110 167 | +11111 1111 1111 1111 1111 1111 1111 0111 168 | 169 | */ 170 | 171 | 相关工具: 172 | 173 | System.out.println(Integer.toBinaryString(-9)); 174 | Integer.toBinaryString(a) :二进制 175 | Integer.toHexString(a):十六进制 176 | Integer.toOctalString(a):八进制 177 | Integer.MAX_VALUE :int类型的最大值 178 | Integer.MIN_VALUE:int类型最小值 179 | 180 | 十六进制转十进制 181 | Integer.valueOf(a+"",16) 182 | 八进制转十进制 183 | Integer.valueOf(a+"",8) 184 | 二进制转十进制 185 | Integer.valueOf(a+"",2) 186 | 187 | 位操作举例: 188 | 189 | System.out.println(6>>2);//6*1/4=1 190 | System.out.println(6<<2);//6*4=24 191 | System.out.println("-6>>2="+(-6>>2));//-6*1/4=-2 192 | System.out.println("-13>>2="+(-13>>2));//-14*1/4=-4 193 | System.out.println("-12>>2="+(-12>>2));//-12*1/4=-3 194 | System.out.println("-6/4="+(-6/4));//-6*1/4=-1 195 | System.out.println("-1/4="+(-1/4));//-1*1/4=0 196 | System.out.println("-6>>>2="+(-6>>>2));//21073741822 197 | 198 | 199 | **最有效的方式计算2\*8 = 2 \* 2^3** 200 | 201 | ` System.out.println(2<<3);` 202 | 203 | 进行两个数互换 204 | 205 | int a = 5 , b = 10; 206 | //第一种方法 207 | int c = a; 208 | a = b ; 209 | b = c; 210 | // 第二种方法 211 | a = a+b; //可能溢出 212 | b = a - b; 213 | a = a - b; 214 | //第三种方法(优先使用) 215 | a = a ^ b ; 216 | b = a^ b;//a ^ b ^ b 217 | a = a ^ b; //a ^ b ^ a 218 | System.out.println("a="+a+",b="+b); 219 | 220 | --- 221 | 222 | 有三个数,获得最大值 223 | 224 | int x = 10 , y = 20 , c = 5; 225 | int t = x > y ? x : y; 226 | int max = t > c ? t : c; 227 | System.out.println("max="+max); 228 | */ 229 | 230 | --- 231 | 232 | 将一个十进制转换为十六进制(位运算符) 233 | 234 | //思路: 235 | /* 236 | 1 转换成二进制,取第四位,判断是不是大于10,如果大于10,则转换成a~f 237 | 2 右移四位,再重复第一步,直到值为0时,中断 238 | */ 239 | int num = 30; //0001 1110 240 | int n = num & 15;//0000 1110 低四位 241 | num = num >> 4 ;//取下一个四位数 242 | char c = (char)(n - 10 + 'a'); 243 | System.out.println("0x"+num+c); 244 | 245 | --- 246 | 247 | 判断闰年 248 | 249 | int year = input.nextInt(); 250 | if(year %4 ==0 && year %100!=0 || year % 400==0){ 251 | System.out.println("闰年"); 252 | } 253 | else{ 254 | System.out.println("平年"); 255 | } 256 | 257 | --- 258 | 259 | 产生随机数 260 | 261 | double Math.random()--->0-1 262 | //Math.random()*(大数-小数+1)+小数 //(小数,大数)范围的数 263 | 264 | --- 265 | 266 | 九九乘法表 267 | 268 | int i = 1; 269 | while(i<=9){ 270 | int j = 1; 271 | do{ 272 | System.out.print(j+"*"+i+"="+i*j+"\t"); 273 | j++; 274 | }while(j<=i); 275 | System.out.println(); 276 | i++; 277 | } 278 | 279 | --- 280 | 菱形 281 | 282 | /* 283 | * 284 | *** 285 | ***** 286 | ******* 287 | ***** 288 | *** 289 | * 290 | 291 | */ 292 | for(int i = 1;i<=4;i++){ //行 293 | //空格 294 | for(int j=1;j<=4-i;j++){ 295 | System.out.print(" "); 296 | } 297 | //变量作用域:从声明的位置开始,到它所在的结构结束为止 298 | //星号 299 | for(int j=1;j<= 2*i-1;j++){ 300 | System.out.print("*"); 301 | } 302 | //换行 303 | System.out.println(); 304 | } 305 | for(int i = 1 ; i<=3 ;i++){ 306 | //空格 307 | for(int j=1;j<=i;j++){ 308 | System.out.print(" "); 309 | } 310 | //星号 311 | for(int j=1;j<=7-2*i;j++){ 312 | System.out.print("*"); 313 | } 314 | //换行 315 | System.out.println(); 316 | } 317 | 318 | --- 319 | 空心菱形 320 | 321 | /* 322 | * 323 | * * 324 | * * 325 | * * 326 | * * 327 | * * 328 | * 329 | */ 330 | for(int i = 1;i<=4;i++){ //行 331 | //空格 332 | for(int j=1;j<=4-i;j++){ 333 | System.out.print(" "); 334 | } 335 | //变量作用域:从声明的位置开始,到它所在的结构结束为止 336 | //星号 337 | for(int j=1;j<= 2*i-1;j++){ 338 | if(j==1 || j==2*i-1) 339 | System.out.print("*"); 340 | else 341 | System.out.print(" "); 342 | } 343 | //换行 344 | System.out.println(); 345 | } 346 | for(int i = 1 ; i<=3 ;i++){ 347 | //空格 348 | for(int j=1;j<=i;j++){ 349 | System.out.print(" "); 350 | } 351 | //星号 352 | for(int j=1;j<=7-2*i;j++){ 353 | if(j==1 || j==7-2*i) 354 | System.out.print("*"); 355 | else 356 | System.out.print(" "); 357 | } 358 | //换行 359 | System.out.println(); 360 | } 361 | 362 | --- 363 | ####switch 结构 364 | switch(表达式){ //byte short int char 枚举(jdk1.5 enum) String(jdk1.7) 365 | case 常量1: 366 | 语句1; 367 | break; 368 | case 常量2: 369 | 语句2; 370 | break; 371 | ... 372 | default: 373 | 语句n; 374 | break; 375 | } 376 | 377 | 注意: 378 | 379 | 1 break可有可无 380 | 2 case后面的常量值一定不能相同。 381 | 3 表达式类型 382 | 4 case后的语句可以省略 383 | switch(表达式){ 384 | case 常量1: 385 | case 常量2: 386 | case 常量3: 387 | 语句1; 388 | break; 389 | 390 | } 391 | 392 | ---- 393 | - for、while、do-while何时采用? 394 | 395 | >已知循环次数:首选for 396 | 循环次数未知:首选while、do-while 397 | 如果循环结束后,循环的变量不需要继续使用,可以for 398 | 399 | - if和switch何时采用? 400 | 401 | >区间判断:if 402 | 等值判断:switch -------------------------------------------------------------------------------- /javaBasic2.md: -------------------------------------------------------------------------------- 1 | ####方法相关 2 | 3 | - 何时采用参数和返回值? 4 | 5 | 1 确定函数有没有结果:即确定是否有返回值 6 | 有结果:有返回值 7 | 没有结果:没有返回值 8 | 2 确定函数在执行过程中,是否用到了不确定的数据:即确定参数 9 | 用到了不确定的数据:有参数 10 | 没用到不确定的数据:无参 11 | 12 | 13 | - 没有返回值方法,也可以使用return 14 | 15 | public static void t1(int a){ 16 | if(a>0){ 17 | return; 18 | } 19 | else{ 20 | System.out.println("a<=0"); 21 | } 22 | } 23 | 24 | 25 | > 方法调用:入栈,分配空间,初始化局部变量 26 | 27 | >方法的返回:出栈,释放空间,在方法中定义的局部变量消失了 28 | 29 | ####递归 30 | 31 | 求阶乘 32 | 33 | public static int f(int n){ 34 | if(n == 1) 35 | return 1; //出口 36 | else 37 | return n * f(n-1); //逐步逼近出口 38 | } 39 | 40 | --- 41 | 斐波那契数列:1 1 2 3 5 8 13 21 34 55 42 | 43 | public static int f(int n){ 44 | if(n==1 || n==2){ 45 | return 1; 46 | } 47 | else{ 48 | return f(n-1) +f(n-2); 49 | } 50 | } 51 | 52 | --- 53 | #### 数组问题 54 | 数组下标必须是 0 ~ arr.length - 1 .否则会出现 55 | **`ArrayIndexOutOfBoundsException`** 56 | 57 | System提供的数组拷贝工具使用: 58 | 59 | **`arraycopy(Object src,int srcPos,Object dest,int destPos,int length)`** 60 | 61 | src:源数组 62 | srcPos:从源数组的那个下标开始拷贝 63 | dest:目标数组 64 | destPos:目标数组的复制的位置 65 | length:复制的数组元素的长度 66 | 67 | 注意:下标越界 68 | 69 | `java.util.Arrays`工具包的使用 70 | 71 | String toString([]):"[1,2,3,4]" 72 | void fill([],num):用num填充数组 73 | boolean equals([],[]):两个数组的元素一一比较 74 | void sort([]):排序 75 | int binarySearch([],key):二分法查找 76 | [] copyOf([],newLength):数组拷贝 77 | 78 | 示例: 79 | 80 | int[] a={2,3,4,6,1,23,45}; 81 | //将数组转换成字符串 toString([]) 82 | System.out.println(Arrays.toString(a)); 83 | //排序 sort([]) 84 | Arrays.sort(a); 85 | System.out.println("排序后的数组:"); 86 | System.out.println(Arrays.toString(a)); 87 | int[] b = new int[10]; 88 | System.out.println(Arrays.toString(b)); 89 | //用指定的数值填充数组b fill([],num) 90 | Arrays.fill(b,5); 91 | System.out.println(Arrays.toString(b)); 92 | int[] c = {1,2,3,4,5}; 93 | int[] d = {1,2,3,5,4}; 94 | //判断数组是否相等 equals([],[]) 95 | System.out.println("数组c和d是否相等?"+Arrays.equals(c,d)); 96 | //二分法查找 binarySearch([],key) 97 | int[] e = {10,20,30,1,2,-4}; 98 | Arrays.sort(e); 99 | System.out.println(Arrays.binarySearch(e,-10));//如果是负数,没找到 100 | //数组的复制 [] copyOf([],newLength) 101 | int[] f = {1,2,3,4,5,6,7,8,9}; 102 | int[] newF = Arrays.copyOf(f,20); 103 | System.out.println(Arrays.toString(newF)); 104 | 105 | 106 | ####JVM 107 | JVM内存一般分**五个区域**: 108 | 109 | ![JVM运行时数据区](http://7xj2yt.com1.z0.glb.clouddn.com/java_JVM.png) 110 | 111 | 112 | 方法区 堆 栈 本地方法区 寄存器 113 | 方法区:存类的信息,常量池,静态方法区 114 | 栈(值类型):存放调用方法的局部变量 115 | 存储在栈中的变量,作用域结束立即消失 116 | 堆(引用类型):存数组或者引用对象 117 | 特点: 118 | 1 分配内存首地址 119 | 2 有默认值 120 | 3 gc(垃圾回收) 121 | 本地方法区:实现类库的调用 122 | 123 | 注意:在常量池中,java默认创建-128-127之间的常量对象 124 | 对于字符串常量会首先去常量池查找,如果不存在就创建字符串常量 125 | 126 | 127 | **值类型**和**引用类型参数**的区别:两个数的互换 128 | 129 | **如果参数为值类型:传递的是值的副本,形参不能改变实参的值** 130 | 131 | **如果参数类型为引用类型:传递的是地址,形参可以改变实参的值** 132 | 133 | --- 134 | 135 | - 字符串常量对象:保存在字符串常量池中 136 | 137 | public static void main(String[] args) 138 | { 139 | String str = "你好"; 140 | String str1 = "你好"; 141 | System.out.println(str==str1); //结果为true 142 | show(str);//将str变量的内容“你好”传递给方法 143 | System.out.println(str); //你好 144 | //下面这条语句创建了几个对象?此时只会创建一个对象,因为”你好“已经在常量池中存在 145 | String str3 = new String("你好"); 146 | String str4 = str3; 147 | str3 = "hi"; //“hi”字符串在常量池不存在,则会在常量池中创建一个对象,str3就指向该对象 148 | System.out.println(str4); //你好 149 | } 150 | static void show(String str){ 151 | str = "hello"; //方法中重新赋值 152 | } 153 | 154 | ####可变参数:jdk5.0新增 155 | 156 | 语法: 157 | 返回类型 方法名(数据类型...参数名){ 158 | 159 | } 160 | 用途:可以动态接受0个或者多个实参,主要应用于方法参数个数不固定 161 | 根据实参的个数,jvm把它处理成数组 162 | 163 | 可变参数:**参数数量可变,类型不能变** 164 | 165 | public static int getSum(int...nums){ 166 | int sum = 0 ; 167 | for(int i=0;i 62 | 63 | class Student 64 | { 65 | static String sex = "男"; //静态成员变量 66 | 67 | private int age; //实例成员变量 68 | 69 | public void setAge(int age){ 70 | this.age = age; 71 | } 72 | 73 | //静态方法 74 | public static void setSex(String sex){ 75 | Student.sex = sex; 76 | //age = 15; //静态方法中不能访问非静态变量 77 | /*Student s = new Student(); //在静态方法中如果想访问实例成员,需要通过对象访问 78 | s.age = 15;*/ 79 | } 80 | //实例方法 81 | public void show(){ 82 | setSex("女"); 83 | System.out.println(sex+" "+ age); 84 | } 85 | } 86 | 87 | --- 88 | ####代码块 89 | 90 | 构造代码块:优先于构造方法执行,主要用于初始化成员变量 91 | 每次创建对象都会执行 92 | 静态代码块:static{},用来初始化静态成员变量。随着类的加载而执行,只执行一次 93 | 注意:在程序优化中,不建议过多的使用static,因为它会长时间保留在内存中 94 | > 95 | 96 | class Demo06 97 | { 98 | public static void main(String[] args) 99 | { 100 | System.out.println("main方法开始执行....."); 101 | { 102 | //普通代码块:作用域 103 | int i= 6; 104 | System.out.println("i-->"+i); 105 | }//i作用域消失 106 | int i = 10; 107 | System.out.println("iiii-->"+i); 108 | 109 | 110 | System.out.println("*****************"); 111 | Student s1 = new Student(); 112 | System.out.println("*****************"); 113 | new Student(); 114 | } 115 | static int num = 10; 116 | int a = 5; 117 | //静态代码块 118 | static{ 119 | System.out.println("静态代码块1"); 120 | System.out.println(num); 121 | //System.out.println(a); //静态代码块中不能直接引用非静态成员 122 | } 123 | static{ 124 | System.out.println("静态代码块2"); 125 | } 126 | 127 | /*如果执行该代码块程序将强制退出 128 | static{ 129 | System.exit(-1); 130 | }*/ 131 | } 132 | 133 | 134 | class Student 135 | { 136 | static int age = 1; 137 | 138 | { 139 | System.out.println("构造代码块1"); 140 | } 141 | { 142 | System.out.println("构造代码块2"); 143 | } 144 | public Student(){ 145 | System.out.println("Student构造方法"); 146 | } 147 | { 148 | System.out.println("构造代码块3"); 149 | } 150 | } 151 | >程序运行结果 152 | > 153 | 静态代码块1 154 | 10 155 | 静态代码块2 156 | main方法开始执行. 157 | i-->6 158 | iiii-->10 159 | ***************** 160 | 构造代码块1 161 | 构造代码块2 162 | 构造代码块3 163 | Student构造方法 164 | ***************** 165 | 构造代码块1 166 | 构造代码块2 167 | 构造代码块3 168 | Student构造方法 169 | 170 | 171 | 这里再看一个例子: 172 | 173 | package Demo; 174 | 175 | /** 176 | * Created by wswenyue 177 | */ 178 | public class Test1 { 179 | public static void main(String[] args) { 180 | System.out.println("------------new 子类-------------"); 181 | new B().f(); 182 | System.out.println("----------new 父类--------------"); 183 | new A().f(); 184 | } 185 | } 186 | 187 | class A { 188 | public int a ; 189 | static { 190 | System.out.println("父类静态代码块1"); 191 | } 192 | public A(){ 193 | System.out.println("父类无参构造方法"); 194 | } 195 | public A(int a){ 196 | this.a = a; 197 | System.out.println("父类有参参构造方法"); 198 | } 199 | 200 | public void f(){ 201 | { 202 | System.out.println("父类方法--普通代码块"); 203 | } 204 | System.out.println("父类方法"); 205 | } 206 | 207 | { 208 | System.out.println("父类普通代码块"); 209 | } 210 | static { 211 | System.out.println("父类静态代码块2"); 212 | } 213 | } 214 | 215 | class B extends A { 216 | public int a ; 217 | static { 218 | System.out.println("子类静态代码块1"); 219 | } 220 | public B(){ 221 | System.out.println("子类无参构造方法"); 222 | } 223 | public B(int a){ 224 | this.a = a; 225 | System.out.println("子类有参参构造方法"); 226 | } 227 | 228 | public void f(){ 229 | { 230 | System.out.println("子类方法--普通代码块"); 231 | } 232 | System.out.println("子类方法"); 233 | } 234 | 235 | { 236 | System.out.println("子类普通代码块"); 237 | } 238 | static { 239 | System.out.println("子类静态代码块2"); 240 | } 241 | } 242 | 243 | 执行结果: 244 | 245 | ------------new 子类------------- 246 | 父类静态代码块1 247 | 父类静态代码块2 248 | 子类静态代码块1 249 | 子类静态代码块2 250 | 父类普通代码块 251 | 父类无参构造方法 252 | 子类普通代码块 253 | 子类无参构造方法 254 | 子类方法--普通代码块 255 | 子类方法 256 | ----------new 父类-------------- 257 | 父类普通代码块 258 | 父类无参构造方法 259 | 父类方法--普通代码块 260 | 父类方法 261 | 262 | ---- 263 | ####对象初始化过程: 264 | 1 加载类的字节码文件到jvm的方法区中 265 | 2 为静态变量在静态区开辟内存空间,赋初始值 266 | 3 加载静态代码块,初始化静态成员变量 267 | 4 开辟堆中空间(成员变量),给成员变量初始化 268 | 5 加载构造代码块 269 | 6 加载构造方法 270 | 7 将堆空间的首地址赋值给栈中对象的引用 271 | 272 | 示例: 273 | 274 | class Demo07 275 | { 276 | public static int age; 277 | static{ //静态代码块 278 | System.out.println("静态代码块"); 279 | System.out.println("age--->"+age); 280 | age = 18; //初始化静态成员变量,在类加载的时候执行 281 | System.out.println("age--->"+age); 282 | } 283 | { 284 | System.out.println("构造代码块"); 285 | //构造代码块 286 | age += 1; 287 | System.out.println("age--->"+age); 288 | } 289 | Demo07(){ 290 | System.out.println("构造方法"); 291 | } 292 | public static void main(String[] args) 293 | { 294 | new Demo07(); 295 | new Demo07(); 296 | new Demo07(); 297 | } 298 | } 299 | > 运行结果 300 | 301 | 静态代码块 302 | age--->0 303 | age--->18 304 | 构造代码块 305 | age--->19 306 | 构造方法 307 | 构造代码块 308 | age--->20 309 | 构造方法 310 | 构造代码块 311 | age--->21 312 | 构造方法 313 | 314 | --- 315 | 316 | ####继承 317 | 子类可以继承父类非私有的成员 318 | 继承的传递性:---多层继承 319 | class A{} 320 | class B extends A{} 321 | class C extends B{} 322 | 323 | #####子类对象初始化过程: 324 | 1 父类静态代码块 325 | 2 子类静态代码块 326 | 3 父类构造代码块 327 | 4 父类构造方法 328 | 5 子类构造代码块 329 | 6 子类构造方法 330 | 示例 331 | 332 | //父类对象 333 | class Parent 334 | { 335 | private String name; 336 | public int age; 337 | static{ 338 | System.out.println("父类的静态代码块"); 339 | } 340 | { 341 | System.out.println("父类的构造代码块"); 342 | } 343 | Parent(){ 344 | System.out.println("父类的构造方法"); 345 | } 346 | public void say(){ 347 | System.out.println("父类age:"+age); 348 | } 349 | } 350 | 351 | //子类对象 352 | class Child extends Parent 353 | { 354 | private int age; 355 | static{ 356 | System.out.println("子类静态代码块"); 357 | } 358 | { 359 | System.out.println("子类构造代码块"); 360 | } 361 | Child(){ 362 | System.out.println("子类构造方法"); 363 | } 364 | public void sayHi(){ 365 | super.age = 100; 366 | this.age = 50; 367 | System.out.println("子类age:"+age); 368 | say(); 369 | } 370 | 371 | //现在我们来调用测试一下 372 | public static void main(String[] args) 373 | { 374 | Child c = new Child(); 375 | c.sayHi(); 376 | } 377 | 378 | 输出结果: 379 | 380 | 父类的静态代码块 381 | 子类静态代码块 382 | 父类的构造代码块 383 | 父类的构造方法 384 | 子类构造代码块 385 | 子类构造方法 386 | 子类age:50 387 | 父类age:100 388 | 389 | --- 390 | 391 | **this和super:** 392 | 393 | this:代表当前对象。this.成员。 394 | this()本类的构造方法,必须在第一行 395 | super:代表父类对象,并不是一个引用,没有父类的指向(因此super不能作为参数传递) 396 | 可以通过super.父类成员来访问父类的成员 397 | 也可以通过super()调用父类的构造方法,必须在第一行 398 | 399 | this()和super()不能同时出现 400 | this和super关键字不能出现在静态方法中 401 | 402 | #####重写(覆盖) 403 | 前提条件 必须继承 404 | 注意: 405 | 1 父类的私有方法不能被重写 406 | 2 子类重写父类的方法时,重写的方法权限必须大于等于父类中的方法权限 407 | 3 静态只能静态覆盖 408 | 4 当父类中的方法有返回类型时,子类重写父类方法时,返回类型可以是父类类型也可以是父类的子类类型 409 | -------------------------------------------------------------------------------- /javaBasic4.md: -------------------------------------------------------------------------------- 1 | ####static 2 | 3 | 修饰变量:类的变量 类名调用 4 | 修饰方法:类的方法 类名调用。只能直接访问静态成员 5 | 修饰内部类:只能修饰静态内部类 6 | 修饰代码块:给静态变量初始化,只执行一次 7 | 8 | ####final关键字:最终的 9 | 10 | final修饰变量:常量,值不能修改 11 | final修饰方法:不能被重写 12 | final修饰类:不能被继承 13 | 14 | ####abstract关键字:抽象的 15 | 16 | 抽象类:abstract修饰的类,抽象类中可以有抽象方法,也可以有非抽象方法。 17 | 抽象类不能实例化对象。 18 | 如果子类继承了抽象类,必须实现抽象类中所有的抽象方法。 19 | 抽象方法:abstract修饰的方法,只有方法声明没有方法的实现。抽象方法必须在抽象类中。 20 | 21 | 思考: 22 | 23 | 1 抽象类一定是父类吗? 一定是父类 24 | 2 抽象类可以有构造方法吗?有,用于子类对象的初始化 25 | 3 有抽象方法的类一定是抽象类吗?一定 26 | 4 抽象类中一定有抽象方法吗?不一定 27 | 5 抽象方法不可以和哪些关键字同时使用? 28 | final:抽象类必须有子类,被final修饰的类不能有子类 29 | static:抽象方法不能被调用,静态方法通过类名调用 30 | private:抽象方法必须是可以被子类重写的,私有方法不能被重写 31 | 32 | ####interface 接口 33 | 34 | 实现接口可以得到该继承体系之外的额外的功能 35 | 接口之间可以多继承 36 | 37 | interface 接口名{ 38 | 抽象方法(public abstract) 39 | 全局常量(public static final) 40 | } 41 | 42 | 接口:interface 规范 43 | 接口可以解决单继承的问题。接口支持多继承。 44 | 子类实现接口是,必须重写接口中的抽象方法。 45 | 创建子类对象时,调用子类重写的方法。 46 | 47 | 接口好处: 48 | 1 规范 49 | 2 提高程序可扩展性 50 | 3 降低类之间的依赖关系 51 | 52 | 示例 53 | 54 | /* 55 | 接口之间可以多继承 56 | */ 57 | interface Ia 58 | { 59 | } 60 | interface Ib 61 | { 62 | } 63 | interface Ic extends Ia,Ib 64 | { 65 | } 66 | 67 | 接口是一种标准(规范) 68 | 69 | class Demo07 70 | { 71 | public static void main(String[] args) 72 | { 73 | IUsb usb = new Computer(); 74 | usb.insert(); 75 | usb.pop(); 76 | } 77 | } 78 | 79 | interface IUsb 80 | { 81 | void insert(); 82 | void pop(); 83 | } 84 | class Computer implements IUsb 85 | { 86 | public void insert(){ 87 | System.out.println("插入usb"); 88 | } 89 | public void pop(){ 90 | System.out.println("弹出usb"); 91 | } 92 | } 93 | 94 | ####多态 95 | 96 | 多态:多种形态 97 | 运行时多态:重写 父类类型引用指向了子类的对象 父类 对象名 = new 子类(); 98 | 编译时多态:重载 99 | 100 | 前提条件:继承或者实现 101 | 102 | 103 | 子类 对象名 = new 子类(); 104 | 可调用的方法:父类继承的方法、子类重写的方法、子类新增的方法 105 | 可执行的方法体:子类重写方法 106 | 107 | 父类 对象名 = new 子类(); 108 | 可调用的方法:父类继承的方法、子类重写的方法 109 | 可执行的方法体:子类重写方法 110 | 111 | #####类型转换 112 | 113 | 基本数据类型: 114 | 自动类型转换 小-->大 115 | 强制类型转换 (小类型)变量 116 | 117 | 引用类型:父类可以看做是大的类型,子类是小的类型 118 | 119 | 子--(向上转型)--》父--(向下转型)--》子 120 | 121 | 猫--->动物--->猫 122 | 狗--->动物--×-->猫 :ClassCastException 类型转换异常 123 | 124 | 注意: 125 | 126 | 向上转型:父类 对象名 = new 子类(); 127 | 向下转型:子类 对象名 = (子类)父类对象; 128 | 前提条件:向上是向下的前提,需要强转 129 | 可能会抛出异常:.ClassCastException 130 | 解决:判断 131 | if(对象 instanceof 类名){} 132 | 133 | 多态中成员的特点: 134 | 成员变量:编译时能访问哪些变量看父类,执行结果看父类 135 | 成员函数:编译时期能访问哪些方法看父类,执行结果看子类(前提子类重写父类的方法,没有重写还是看父类) 136 | 静态成员函数:编译执行都看父类 137 | 138 | 139 | 多态示例: 140 | 141 | class Demo10 142 | { 143 | /* 144 | 多态: 145 | */ 146 | public static void main(String[] args) 147 | { 148 | //父类 对象名 = new 子类(); 149 | Animal cat = new Cat(); 150 | cat.eat(); //从父类继承的方法、子类重写的方法 151 | cat.f(); //调用、执行均看父类 152 | 153 | Animal dog = new Dog(); 154 | dog.eat(); 155 | 156 | 157 | chi(dog); 158 | System.out.println("------------------"); 159 | 160 | Animal a1 = new Cat(); 161 | Animal a2 = new Dog(); 162 | 163 | if(a1 instanceof Cat){ 164 | Cat c1 = (Cat)a1 ; //父类继承的方法 子类重写的方法 子类新增的方法 165 | c1.eat(); 166 | c1.catchMouse(); 167 | System.out.println("恭喜你,成功变回猫"); 168 | }else{ 169 | System.out.println("你本不是一只猫"); 170 | } 171 | 172 | System.out.println("------------------"); 173 | if(a2 instanceof Cat){ 174 | System.out.println("恭喜你,成功变回猫"); 175 | Cat c2 = (Cat)a2; //狗不能转成猫 176 | c2.eat(); 177 | c2.catchMouse(); 178 | } 179 | else{ 180 | System.out.println("你本不是一只猫"); 181 | } 182 | System.out.println("------------------"); 183 | if(a2 instanceof Dog){ 184 | ((Dog)a2).eat(); 185 | ((Dog)a2).watchHome(); 186 | System.out.println("终于变回狗了"); 187 | } 188 | } 189 | /* 190 | public static void chi(Cat c){ 191 | c.eat(); 192 | } 193 | public static void chi(Dog d){ 194 | d.eat(); 195 | }*/ 196 | public static void chi(Animal a){ 197 | a.eat(); 198 | } 199 | } 200 | abstract class Animal 201 | { 202 | public abstract void eat(); 203 | public static void f(){ 204 | System.out.println("Animal static "); 205 | } 206 | } 207 | class Cat extends Animal 208 | { 209 | public void eat(){ 210 | System.out.println("猫吃鱼"); 211 | } 212 | public void catchMouse(){ 213 | 214 | System.out.println("猫抓老鼠"); 215 | } 216 | public static void f(){ 217 | System.out.println("Cat static "); 218 | } 219 | } 220 | class Dog extends Animal 221 | { 222 | public void eat(){ 223 | System.out.println("狗吃骨头"); 224 | } 225 | public void watchHome(){ 226 | System.out.println("狗看家"); 227 | } 228 | } 229 | 230 | 231 | 232 | ---- 233 | 234 | ####内部类 235 | - 成员内部类 236 | - 静态内部类 237 | - 局部内部类 238 | - 匿名内部类 239 | 240 | 特点: 241 | > 内部类可以直接访问外部类成员 242 | > 外部类要访问内部类的成员,必须建立内部类的对象 243 | 244 | 作用: 245 | > 1 隐藏部分信息 246 | 2 可以访问外部类的私有成员 247 | 3 弥补了单继承的局限性 248 | 4 解决问题:如果要描述一个事物中还包括另一个事物,同时这个事物要访问被描述的事物 249 | 250 | 251 | 生成字节码文件:外部类$内部类.class 252 | 253 | #####成员内部类 254 | 成员内部类处在了外部类成员的位置上,所以内部类可以直接访问外部类的成员 255 | 256 | 代码示例: 257 | 258 | [public/default]class 外部类{ 259 | 属性 260 | 方法 261 | 内部类: 262 | [访问修饰符] class 内部类{ //public private default protected 263 | 属性 264 | 方法 265 | } 266 | } 267 | 268 | 说明: 269 | 270 | 1 内部类可以直接调用外部类的成员,包括private 271 | 2 如果内部类与外部类的属性或者方法同名时,则内部类默认调用内部类自己的。 272 | 如果想调用外部类的 273 | 外部类.this.成员 274 | 3 创建内部类对象 275 | 1) 276 | 外部类 外部类对象 = new 外部类(); 277 | 外部类.内部类 内部类对象 = 外部类对象.new 内部类(); 278 | 2) 279 | 外部类.内部类 内部类对象 = new 外部类().new 内部类(); 280 | 4 如果外部类想调用内部类成员,需要通过创建内部类对象来调用。 281 | 5 编译之后生成的内部类字节码文件为:外部类$内部类.class 282 | 283 | 示例: 284 | 285 | class Demo13 286 | { 287 | public static void main(String[] args) 288 | { 289 | Outer1 out = new Outer1(); 290 | out.test(); 291 | System.out.println("通过创建内部类对象访问内部类成员"); 292 | Outer1.Inner1 inner = new Outer1().new Inner1(); 293 | inner.show(); 294 | } 295 | } 296 | 297 | class Outer1 298 | { 299 | private int num = 5; 300 | class Inner1 //成员内部类 301 | { 302 | int num = 500; 303 | public void show(){ 304 | System.out.println("inner-->num="+num); 305 | System.out.println("outer-->num="+Outer1.this.num); 306 | } 307 | } 308 | 309 | public void test(){ //外部类的方法 310 | Inner1 in = new Inner1();//外部类访问内部类成员,需要通过对象访问 311 | in.show(); 312 | } 313 | } 314 | 315 | #####静态内部类 316 | 静态内部类:相当于外部类,因为static修饰在初始化外部类时就已经被加载到内存中了 317 | 318 | 写法示例: 319 | 320 | [public|default] class 外部类{ 321 | 属性 322 | 方法 323 | //静态内部类 324 | [访问修饰符] static class 内部类{ 325 | 属性 326 | 方法 327 | } 328 | } 329 | 330 | 注意: 331 | 332 | 1 不能调用外部类非静态成员 333 | 2 允许定义非静态的变量和方法 334 | 3 内部类中不能使用 外部类.this 335 | 4 静态内部类使用的格式(不依赖于外部类对象) 336 | 外部类.内部类 内部类对象 = new 外部类.内部类() 337 | 338 | 示例: 339 | 340 | class Demo14 341 | { 342 | public static void main(String[] args) 343 | { 344 | Outer2 out = new Outer2(); 345 | out.test(); 346 | System.out.println("直接访问内部类方法"); 347 | //调用静态内部类中的非静态方法 348 | Outer2.Inner2 in = new Outer2.Inner2(); 349 | in.show(); 350 | System.out.println("-------------"); 351 | //调用静态内部类中的静态方法 352 | Outer2.Inner2.show(); 353 | } 354 | } 355 | class Outer2 356 | { 357 | static int num = 10; 358 | static class Inner2 //静态内部类 359 | { 360 | public static void show(){ 361 | System.out.println("num="+num); 362 | } 363 | 364 | } 365 | 366 | public void test(){ 367 | //Inner2.show(); 368 | Inner2 in = new Inner2(); 369 | in.show(); 370 | } 371 | } 372 | 373 | #####局部内部类 374 | 局部内部类:定义在方法的内部 375 | 376 | 写法示例: 377 | 378 | [public|default] class 外部类{ 379 | 属性 380 | 方法(){ 381 | class 内部类{ 382 | 383 | } 384 | } 385 | } 386 | 387 | 应用:多线程、网络下载 388 | 389 | 注意: 390 | 391 | - 1 局部内部类或者局部方法的访问修饰符只能是default的 392 | - 2 局部内部类可以访问外部类成员 393 | - 3 **局部内部类如果想使用所在方法的局部变量时,该变量必须是final的(因为final存在于方法区,生命周期较长,不影响局部内部类的使用)** 394 | - 4 局部内部类定义在方法中,适用范围仅在方法内 395 | 396 | 示例代码: 397 | 398 | class Demo16 399 | { 400 | public static void main(String[] args) 401 | { 402 | Outer3 out = new Outer3(); 403 | out.test(); 404 | } 405 | } 406 | class Outer3 407 | { 408 | int a = 5; 409 | void test(){ 410 | final int b = 100; 411 | class Inner3 412 | { 413 | public void show(){ 414 | System.out.println("外部类成员a="+a); 415 | System.out.println("方法中的成员b="+b); 416 | } 417 | }//end class 418 | Inner3 in = new Inner3(); 419 | in.show(); 420 | }//end test() 421 | } 422 | 423 | 424 | ##### 匿名内部类 425 | 426 | 匿名内部类: 427 | > 内部类的简写,没有类名。只使用一次对象时,才会定义匿名内部类 428 | 429 | 前提: 430 | > 匿名内部类必须继承或者实现一个外部类或者接口 431 | 432 | 应用: 433 | > 应用于抽象类和接口,增加程序的灵活性 434 | 435 | 语法: 436 | 437 | 类名 对象名 = new 类名(){ //抽象类或者接口的名字 438 | 将抽象类或者接口的方法实现 439 | }; 440 | 441 | 442 | 示例代码一: 443 | 444 | class Demo18 445 | { 446 | /* 447 | 匿名内部类没有类名 448 | */ 449 | class Inner5 implements IUsb 450 | { 451 | public void insert(){ 452 | System.out.println("插入"); 453 | } 454 | public void pop(){ 455 | System.out.println("弹出"); 456 | } 457 | } 458 | 459 | public static void main(String[] args) 460 | { 461 | Demo18.Inner5 i = new Demo18().new Inner5(); 462 | i.insert(); 463 | i.pop(); 464 | 465 | IUsb computer = new IUsb(){ 466 | public void insert(){ 467 | System.out.println("插入"); 468 | } 469 | public void pop(){ 470 | System.out.println("弹出"); 471 | } 472 | }; 473 | computer.insert(); 474 | computer.pop(); 475 | 476 | new IUsb(){ 477 | public void insert(){ 478 | System.out.println("插入1"); 479 | } 480 | public void pop(){ 481 | System.out.println("弹出1"); 482 | } 483 | }.insert(); 484 | } 485 | } 486 | 487 | interface IUsb 488 | { 489 | void insert(); 490 | void pop(); 491 | } 492 | 493 | 494 | 示例代码二: 495 | 496 | class Demo19 497 | { 498 | public static void main(String[] args) 499 | { 500 | Person p = new Person(){ 501 | public void run(){ 502 | System.out.println("人跑步"); 503 | } 504 | }; 505 | p.run(); 506 | 507 | Person p1 = new Person(){ 508 | public void run(){ 509 | System.out.println("人飞奔"); 510 | } 511 | }; 512 | p1.run(); 513 | 514 | 515 | new Person(){ 516 | public void run(){ 517 | System.out.println("散步"); 518 | } 519 | }.run(); 520 | 521 | } 522 | } 523 | abstract class Person{ 524 | public abstract void run(); 525 | } 526 | 527 | 示例代码三(点击事件监听器的应用): 528 | 529 | class Demo20 530 | { 531 | public static void main(String[] args) 532 | { 533 | MyButton myBtn = new MyButton(); 534 | myBtn.isClick = true; 535 | myBtn.setOnClickListener(new OnClickListener(){ 536 | public void onClick(){ 537 | System.out.println("点击了,可以登录!!"); 538 | } 539 | }); 540 | 541 | MyButton myBtn1 = new MyButton(); 542 | myBtn1.isClick = false; 543 | myBtn1.setOnClickListener(new OnClickListener(){ 544 | public void onClick(){ 545 | System.out.println("点击了,找回密码"); 546 | } 547 | }); 548 | } 549 | } 550 | interface OnClickListener 551 | { 552 | void onClick(); 553 | } 554 | class MyButton 555 | { 556 | boolean isClick; //模拟点击 557 | public void setOnClickListener(OnClickListener ocl){ 558 | if(isClick){ 559 | ocl.onClick(); 560 | }else{ 561 | System.out.println("没有点击"); 562 | } 563 | } 564 | } 565 | 566 | 567 | 568 | -------------------------------------------------------------------------------- /javaBasic5.md: -------------------------------------------------------------------------------- 1 | 主要内容:常用类 2 | **String、StringBuffer、Math、Date、Calendar**的使用 3 | 4 | ### String 5 | 6 | -------------------------------------------------------------------------------- /常用算法.md: -------------------------------------------------------------------------------- 1 | ##常用算法 2 | ###排序 3 | 4 | **冒泡排序** 5 | 6 | >冒泡:比较两个相邻的数:左边小,右边大 7 | 8 | - 算法实现 9 | 10 | ```java 11 | 冒泡排序:比较相邻的两个数,小的在左边,大的在右边 12 | public static void bubbleSort(int[] a){ 13 | for(int i = 0;ia[j+1]){ 16 | int t = a[j]; 17 | a[j] = a[j+1]; 18 | a[j+1]= t; 19 | } 20 | } 21 | } 22 | } 23 | ``` 24 | 25 | **选择排序** 26 | 27 | > 选择:每趟基准值,用于存储最小 28 | 29 | - 算法实现 30 | 31 | ```java 32 | public static void selectSort1(int[] a){ 33 | for(int i=0;ia[j]){ 36 | int t = a[i]; 37 | a[i] = a[j]; 38 | a[j] = t; 39 | } 40 | } 41 | } 42 | ``` 43 | 44 | **选择排序---增强版 效率高(建议使用)** 45 | 46 | ```java 47 | public static void selectSort(int[] a){ 48 | for(int i=0;ia[j]){ 52 | minIndex = j; 53 | } 54 | } 55 | //循环结束 56 | if(minIndex!=i){ 57 | int t = a[i]; 58 | a[i] = a[minIndex]; 59 | a[minIndex] = t; 60 | } 61 | } 62 | } 63 | ``` 64 | 65 | **插入排序** 66 | 67 | > 插入:从第二个数值开始,向前边的数列插入保持原有的顺序 68 | 69 | - 算法实现 70 | 71 | ```java 72 | //插入排序:默认左边的数是有序的 73 | public static void insertSort(int[] a){ 74 | for(int i = 1 ; i0;j--){ 76 | if(a[j] 顺序:挨个比较 94 | 95 | - 算法实现 96 | 97 | >顺序查找:如果找到了,返回对应的下标,如果没有找到返回-1 98 | 99 | ```java 100 | /* 101 | 顺序查找:如果出现了数组中元素重复的情况,不保证找到的是哪一个 102 | */ 103 | static int find(int[] a,int key){ 104 | for(int i=0;i 二分:前提:有序 折半查找 116 | 117 | - 算法实现 118 | 119 | ```java 120 | /* 121 | 二分法查找:前提:必须数组有序 122 | 确定中间位置: 123 | */ 124 | static int binaryFind(int[] a,int key){ 125 | int low = 0 ; 126 | int high = a.length - 1; 127 | int mid = 0; 128 | while(low<=high){ 129 | mid = (low+high)/2;//也可以这样写:mid = (low+high)>>1; 130 | if(a[mid]>key){ //左边区域查找 131 | high = mid - 1; 132 | } 133 | else if(a[mid]这儿**super不是指向父类对象的引用地址**,new出来的才在堆里面分配空间有引用地址,这儿没有去new一个父类对象,只是执行了父类的构造函数将父类的特征生成了,但是属于New出来的那个子类对象的 37 | 38 | 实践一下,你可以写 39 | 40 | public FatherClass getThis() 41 | { 42 | return this; 43 | } 44 | 45 | 编译通过,没有任何问题 46 | 但是你写 47 | 48 | public FatherClass getSuper() 49 | { 50 | return super; 51 | } 52 | 53 | 嘿嘿,编译出错! 为什么啦? 54 | 55 | - 因为super并不是一个堆空间里面的一个对象的引用地址,而this才是堆空间里面的一个对象的引用地址 56 | - super只能在对象内部使用,而this可以在对象内部使用也可以返回出对象外. 57 | - super是死的,编译的时候就定死了super的指向了,而this是活的,在运行时候决定其指向. 58 | 59 | 解释一下: 60 | >子类实例化对象,并没有去实例化他的父类对象,也就是说,那个子类对象里面并没有一个父类对象,那你说没有父类对象,为什么子类构造函数要执行父类的构造函数啦,那是因为需要创建父类的特征赋予子类,但是是由子类所有,而super就是用来区别是是否是父类对象的特征的. 61 | 重写父类方法属性,就是再创建了一个子类的特征,当你用this的时候,就覆盖了父类的特征了,但是父类特征还在那儿,用super就能访问到,但是只能在对象的内部使用.对象外面就只能看到覆盖了父类特征的子类特征了. 62 | 63 | 64 | 区别|this|super 65 | ----|----|---- 66 | 访问属性|this.属性名。只能访问当前对象所拥有的属性(包括继承来的属性,如果继承的属性名和子类对象相同,若不指定则调用子类的,调用父类的需要显示指定:super.属性名)|super.属性名。可以访问父类非私有的属性 67 | 访问方法|与访问属性类似|与访问属性类似 68 | 调用构造器|this(有参或无参)调用本类中有参或无参的构造函数,必须放在构造函数的第一句|super(有参还是无参)调用父类的有参或是无参的构造方法,必须放在构造方法的第一行(注意:**在同一个构造函数里不能同时出现this()和super()**) 69 | 指代|this是当前对象在堆空间的引用地址|super是当前对象的父类特征的引用 70 | 作为参数|this可以作为参数,它代表了当前对象的引用|super不可以 71 | 使用环境|不可以在static环境中使用|不可以在static环境中使用 72 | 73 | 74 | ----- 75 | 76 | 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /正则.md: -------------------------------------------------------------------------------- 1 | #正则表达式 2 | **转变你的思维一切当做字符处理** 3 | 4 | 正则:具有一定规则的表达式,用于验证、匹配字符串。 5 | ###元字符: 6 | 7 | 字符|意义 8 | ---|--- 9 | `.` | **匹配除换行符以外的任意字符** 10 | `\d`| **任意数字** 11 | `\D` |**非数字 [^0-9]** 12 | `\w` |**字母 数字 _** 13 | `\W` |**[^a-zA-Z0-9_]** 14 | `\s` |**任意空白字符** 15 | `\S` | **匹配任意不是空白符的字符(例子:** `\S+` **匹配不包含空白符的字符串)** 16 | `\b` |**边界** 17 | `\` |**转义字符** 18 | `^` | **匹配字符串的开始(一行的开头)** 19 | `[^x]` | **匹配除了x以外的任意字符(例子:** `]+>` **匹配用 尖括号括起来的以a开头的字符串。)** 20 | `^aeiou]` | **匹配除了aeiou这几个字母以外的任意字符** 21 | `$` | **匹配字符串的结束(匹配必须出现在字符串的末尾或出现在行或字符串末尾的 \n 之前.)** 22 | 23 | 字符|意义 24 | ----|---- 25 | `?` |**出现0次或者1次** 26 | `*` |**出现0次或者多次** 27 | `+` |**出现1次或者多次**相当于 `{1,}` 28 | `{m}` |**出现m次** 29 | `{m,}` |**至少出现m次** 30 | `{m,n}` |**出现m~n次** 31 | 32 | 33 | `(x|y)` **: x或y** 34 | `[]` **: 任意一个字符** 35 | 36 | [abc]:a b c 中的任意一个字符 37 | [a-z]:任意一个小写字母 38 | [A-Z]:任意一个大写字母 39 | [a-zA-Z]:任意一个字母 40 | [a-d[m-p]]:abcdmnop,取并集 41 | [0-9]:任意一个数字 42 | 43 | 44 | **中文:** `[\u4e00-\u9fa5]` 45 | 46 | ###分支条件 47 | 如果满足其中任意一种规则都应该当成匹配,具体方法是用|把不同的规则分隔开。 48 | 当然**分支的顺序也很重要**: 49 | 例如: 50 | `\d{5}-\d{4}|\d{5}`这个表达式用于匹配美国的邮政编码。美国邮编 的规则是5位数字,或者用连字号间隔的9位数字。之所以要给出这个例子是因为它能说明一个问题:使用分枝条件时,要注意各个条件的顺序。 如果你把它改成`\d{5}|\d{5}-\d{4}`的话,那么就只会匹配5位的邮编(以及9位邮 编的前5位)。原因是匹配分枝条件时,将会从左到右地测试每个条件,如果满足了某个分枝的话,就不会去再管其它的条件了。 51 | 52 | ###分组概念 53 | **分组** `()` 54 | `(.)` 第一组:第一组内容的含义为:任意字符 55 | 56 | **引用** `\num` 57 | `\num` : 引用组(num代表组号) 组的编号从1开始(注:分组0对应整个正则表达式) 58 | `$1` : **上一个正则表达式中第一组的内容** 59 | 例如:`\1` **:引用第一组的内容** 60 | 61 | 例如(用来匹配重复出现的单词): 62 | `\b(\w+)\b\s+\1\b` 可以用来匹配重复的单词,像`go` `go`, 或者`kitty` `kitty`。这个表达式首先是一个单词, 也就是单词开始处和结束处之间的多于一个的字母或数字`(\b(\w+)\b)`, 这个单词会被捕获到编号为1的分组中,然后是1个或几个空白符`(\s+)`,最后是分组1中捕获的内容(也就是前面匹配的那个单词)`(\1)`。 63 | 64 | 例如: 65 | 66 | String s2 = "asffasdfd^^^^dasd@@@@fe%%%seadflj000klajsdf"; 67 | //按照重复的字符串进行切割 68 | String[] arr = s2.split("(.)\\1+"); 69 | 70 | String s4 = "aaabbbbbbddddddeeeeeeee####%%%CCCC"; 71 | //去掉重复的abde#%C 72 | System.out.println(s4.replaceAll("(.)\\1+","$1"));//$1:上一个正则表达式中第一组的内容 73 | 74 | ###零宽断言 75 | 76 | 语法(exp:表达式)|说明 77 | ----|---- 78 | `(?=exp)` | **匹配exp前面的位置** 79 | `(?<=exp)` | **匹配exp后面的位置** 80 | `(?!exp)` | **匹配后面跟的不是exp的位置** 81 | `(?).*(?=<\/\1>)`**匹 配不包含属性的简单HTML标签内里的内容**。 110 | `()`指定了这样的前缀:被尖括号括起来的单词(比 如可能是``),然后是`.*`(任意的字符串),最后是一个后缀`(?=<\/\1>)`。注意后缀里的`\/`,它用到了前面提过的字符转义;`\1`则是一个反向引用,引用的正是捕获的第一组,前面的`(\w+)`匹配的内容,这样如果前缀实际上是``的话,后缀就是``了。整个表达式匹配的是``和``之间的内容(再次提醒,不包括前缀和后缀本身)。 111 | 112 | ###贪婪与懒惰 113 | **贪婪匹配** 114 | 115 | 在使用修饰匹配次数的特殊符号时,有几种表示方法可以使同一个表达式能够匹配不同的次数,比如:"`{m,n}`", "`{m,}`", "`?`", "`*`", "`+`",具体匹配的次数随被匹配的字符串而定。**这种重复匹配不定次数的表达式在匹配过程中,总是尽可能多的匹配**。 116 | 117 | 比如,针对文本 "`dxxxdxxxd`",举例如下: 118 | 119 | 表达式|匹配结果 120 | ------|------- 121 | `(d)(\w+)` | "`\w+`" 将匹配第一个 "`d`" 之后的所有字符 "`xxxdxxxd`" 122 | `(d)(\w+)(d)` | "`\w+`" 将匹配第一个 "`d`" 和最后一个 "`d`" 之间的所有字符 "`xxxdxxx`"。虽然 "`\w+`" 也能够匹配上最后一个 "`d`",但是为了使整个表达式匹配成功,"`\w+`" 可以 "让出" 它本来能够匹配的最后一个 "`d`" 123 | 124 | 由此可见,"`\w+`" 在匹配的时候,总是尽可能多的匹配符合它规则的字符。虽然第二个举例中,它没有匹配最后一个 "`d`",但那也是为了让整个表达式能够匹配成功。同理,带 "`*`" 和 "`{m,n}`" 的表达式都是尽可能地多匹配,带 "`?`" 的表达式在可匹配可不匹配的时候,也是尽可能的 "要匹配"。这 种匹配原则就叫作 "贪婪" 模式 。 125 | 126 | **懒惰匹配** 127 | 在修饰匹配次数的特殊符号后再加上一个 "`?`" 号,则可以使匹配次数不定的表达式尽可能少的匹配,使可匹配可不匹配的表达式,尽可能的 "不匹配"。这种匹配原则叫作 "懒惰" 模式,也叫作 "勉强" 模式。如果少匹配就会导致整个表达式匹配失败的时候,与贪婪模式类似,懒惰模式会最小限度的再匹配一些,以使整个表达式匹配成功。 128 | 举例如下,针对文本 "`dxxxdxxxd`" 举例: 129 | 130 | 表达式|匹配结果 131 | -----|-------- 132 | `(d)(\w+?)` |"`\w+?`" 将尽可能少的匹配第一个 "`d`" 之后的字符,结果是:"`\w+?`" 只匹配了一个 "`x`" 133 | `(d)(\w+?)(d)` | 为了让整个表达式匹配成功,"`\w+?`" 不得不匹配 "`xxx`" 才可以让后边的 "`d`" 匹配,从而使整个表达式匹配成功。因此,结果是:"`\w+?`" 匹配 "`xxx`" 134 | 135 | **懒惰限定符** 136 | 137 | 语法|说明 138 | ----|---- 139 | `*?` | 重复任意次,但尽可能少重复 140 | `+?` | 重复1次或更多次,但尽可能少重复 141 | `??` | 重复0次或1次,但尽可能少重复 142 | `{n,m}?` | 重复n到m次,但尽可能少重复 143 | `{n,}?` | 重复n次以上,但尽可能少重复 144 | 145 | ----- 146 | ###JAVA jdk提供的正则类: 147 | 148 | **Pattern类** 149 | 150 | Pattern p = Pattern.compile("\\d"); 151 | Matcher m = p.matcher("ass923asdf"); 152 | boolean b = m.matches(); 153 | 154 | **String类: matches()** 155 | 156 | String reg = "\\d"; 157 | String str = "123"; 158 | str.matches(reg); 159 | 160 | str.replaceAll(reg,"") 161 | str.split(reg) 162 | 163 | ##正则示例: 164 | 165 | 166 | **邮编**:六位数字 167 | 168 | [0-9]{6} 169 | 或 170 | \d{6} 171 | 或 172 | [1-9]\d{5}(?!\d) //这一个是用的最多的版本 173 | 174 | **手机号码**:1开头,第二位3 4 5 7 8 9 ,其余任意 175 | 176 | 1[345789]\d{9} 177 | 178 | **邮箱**:用户名是字母 数字 _ . -组成, @ xxx . xxx 179 | 180 | (\w|\.|-)+@\w+\.\w+ [a-zA-Z0-9_.-]+@\w+\.\w+ 181 | 或 182 | \w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)* 183 | 184 | **身份证号**:18位数字 或者17位数字+xX 185 | 186 | [1-9]\d{16}(\d|[xX]) 187 | 188 | **ip地址**:0-255.0-255.0-255.0-255 189 | 190 | (\d|([1-9]\d)|(1[0-9][0-9])|(2[0-4]\d)|(25[0-5]))\. 191 | 或 192 | ((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?) 193 | 194 | **用户名**:字母 _ 数字 - 组成,6-18位 195 | 196 | (\w|-){6,18} 197 | 198 | **匹配帐号是否合法**(字母开头,允许5-16字节,允许字母数字下划线): 199 | 200 | ^[a-zA-Z][a-zA-Z0-9_]{4,15}$ 201 | 202 | **qq号**:10000以上 203 | 204 | [1-9][0-9]{4,} 205 | 206 | **出生日期** XXXX-XX-XX XX-x-X XXXX-X-X XX-XX-XX 207 | 208 | 1900-2015 01-12 01-31 209 | ((19)?\d{2}|(20)?(0\d|1[0-5]))- 210 | (0?[1-9]|1[0-2])- 211 | (0?[1-9]|[12]\d|3[01]) 212 | 213 | 匹配**双字节字符**(包括汉字在内) 214 | 可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1) 215 | 216 | [^\x00-\xff] 217 | 218 | 匹配**空白行**(可以用来删除空白行): 219 | 220 | \n\s*\r 221 | 或 222 | \n[\s| ]*\r 223 | 224 | **匹配HTML标记**(这个也仅仅能匹配部分,对于复杂的嵌套标记依旧无能为力) 225 | 226 | <(\S*?)[^>]*>.*?|<.*? /> 227 | 或 228 | /<(.*)>.*<\/\1>|<(.*) \/>/ 229 | 230 | **匹配首尾空白字符** 231 | 可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等) 232 | 233 | ^\s*|\s*$ 234 | 或 235 | (^\s*)|(\s*$) 236 | 237 | **匹配网址URL** 238 | 这个基本可以满足需求 239 | 240 | [a-zA-z]+://[^\s]* 241 | 242 | **匹配国内电话号码**: 243 | 匹配形式如 0511-4405222 或 021-87888822 244 | 245 | \d{3}-\d{8}|\d{4}-\d{7} 246 | 247 | 匹配特定数字: 248 | 249 | ^[1-9]\d*$    //匹配正整数 250 | ^-[1-9]\d*$   //匹配负整数 251 | ^-?[1-9]\d*$   //匹配整数 252 | ^[1-9]\d*|0$  //匹配非负整数(正整数 + 0) 253 | ^-[1-9]\d*|0$   //匹配非正整数(负整数 + 0) 254 | ^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$   //匹配正浮点数 255 | ^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$  //匹配负浮点数 256 | ^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$  //匹配浮点数 257 | ^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$   //匹配非负浮点数(正浮点数 + 0) 258 | ^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$  //匹配非正浮点数(负浮点数 + 0) 259 | 260 | 匹配特定字符串: 261 | 262 | ^[A-Za-z]+$  //匹配由26个英文字母组成的字符串 263 | ^[A-Z]+$  //匹配由26个英文字母的大写组成的字符串 264 | ^[a-z]+$  //匹配由26个英文字母的小写组成的字符串 265 | ^[A-Za-z0-9]+$  //匹配由数字和26个英文字母组成的字符串 266 | ^\w+$  //匹配由数字、26个英文字母或者下划线组成的字符串 267 | 268 | 269 | **常用正则表达式** 270 | 271 | > 说明:正则表达式通常用于两种任务:1.验证,2.搜索/替换。用于验证时,通常需要在前后分别加上`^`和`$`,以匹配整个待验证字符串;搜索/替换时是否加上此限定则根据搜索的要求而定,此外,也有可能要在前后加上\b而不是^和$。此表所列的常用正则表达式,除个别外均未在前后加上任何限定,请根据需要,自行处理。 272 | 273 | 274 | 说明|表达式 275 | ----|----- 276 | 网址(URL)| `[a-zA-z]+://[^\s]*` 277 | 电子邮件(Email) | `\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*` 278 | QQ号码 | `[1-9]\d{4,}` 279 | 密码(由数字/大写字母/小写字母/标点符号组成,四种都必有,8位以上) | `(?=^.{8,}$)(?=.*\d)(?=.*\W+)(?=.*[A-Z])(?=.*[a-z])(?!.*\n).*$` 280 | 汉字(字符)|`[\u4e00-\u9fa5]` 281 | 中文及全角标点符号(字符) | `[\u3000-\u301e\ufe10-\ufe19\ufe30-\ufe44\ufe50-\ufe6b\uff01-\uffee]` 282 | 中国大陆手机号码 | `1\d{10}` 283 | 中国大陆邮政编码 | `[1-9]\d{5}` 284 | 中国大陆身份证号(15位或18位) | `\d{15}(\d\d[0-9xX])?` 285 | 非负整数(正整数或零) | `\d+` 286 | 正整数 | `[0-9]*[1-9][0-9]*` 287 | 整数 | `-?\d+` 288 | 小数 | `(-?\d+)(\.\d+)?` 289 | 不包含abc的单词 | `\b((?!abc)\w)+\b` 290 | 291 | **中国大陆固定电话号码** : 292 | 293 | (\d{4}-|\d{3}-)?(\d{8}|\d{7}) 294 | 295 | **IP地址(IP Address)**: 296 | 297 | ``` 298 | ((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?) 299 | ``` 300 | 301 | 302 | HTML标记(包含内容或自闭合) 303 | 304 | ``` 305 | <(.*)(.*)>.*<\/\1>|<(.*) \/> 306 | ``` 307 | 308 | 日期(年-月-日) 309 | 310 | (\d{4}|\d{2})-((1[0-2])|(0?[1-9]))-(([12][0-9])|(3[01])|(0?[1-9])) 311 | 312 | **时间(小时:分钟, 24小时制)** 313 | 314 | ((1|0?)[0-9]|2[0-3]):([0-5][0-9]) 315 | -------------------------------------------------------------------------------- /网络/htmlStrHandle.md: -------------------------------------------------------------------------------- 1 | #HTML格式的字符串处理的方法总结 2 | >主要的字符串的拼接处理 3 | 4 | 过滤器,**将相应的字符转换为html代码**,转换包括以下字符 `
` `&` `\n` `<` `>` `\` 及`空格` 5 | 6 | private static String[][] _chars={ 7 | {"&", "&"}, 8 | {"\n", "
"}, 9 | {"<", "<"}, 10 | {">", ">"}, 11 | {" ", " "}, 12 | {"\"", """} 13 | }; 14 | 15 | /** 16 | * 过滤器,将相应的字符转换为html代码,转换包括以下字符
17 | * & \n < > \ 及空格 18 | * @param str 19 | * @return newStr 20 | */ 21 | public static String filter(String str) { 22 | for (int i = 0; i < _chars.length; i++) { 23 | str = str.replaceAll(_chars[i][0], _chars[i][1]); 24 | } 25 | return str; 26 | } 27 | 28 | **去除字符串中的html换行符**: `p` ,`br`, 29 | 30 | /** 31 | * 去除字符串中的html换行符: p br, 32 | * @param source 原始字符 33 | * @return newStr 清除后的字符 34 | */ 35 | public static String clearBR(String source) { 36 | String regx = "()|(?)"; 37 | Pattern p = Pattern.compile(regx, Pattern.CASE_INSENSITIVE); 38 | Matcher m = p.matcher(source); 39 | StringBuffer sb = new StringBuffer(); 40 | while (m.find()) { 41 | m.appendReplacement(sb, ""); 42 | } 43 | m.appendTail(sb); 44 | return sb.toString(); 45 | } 46 | 47 | **获取字符串中子串的起始和结束位置**: 48 | 49 | /** 50 | * 从一个字串source中查找find指定的字符串,并返回匹配第一个find所指定的字符串的 51 | * 起始位置(不分大小),该起始位置包含起始字符位置及结速字符位置,获取数据方法
52 | * fin[0] -> find所指定的字符的起始位置,没匹配则返回 -1,
53 | * fin[1] -> find所指定的字符的结速位置,没匹配则返回 -1,
54 | * @param source 源字符串 55 | * @param find 所要查找的字符 56 | * @return fin find所指定的字符在source中的起始位置数组 57 | */ 58 | public static int[] findString(String source, String find) { 59 | int[] fin = new int[]{-1, -1}; 60 | Pattern p = Pattern.compile(find, Pattern.CASE_INSENSITIVE); 61 | Matcher m = p.matcher(source); 62 | if (m.find()) { 63 | fin[0] = m.start(); 64 | fin[1] = m.end(); 65 | } 66 | return fin; 67 | } 68 | 69 | **查询html中指定字符串的,并高亮显示**: 70 | 71 | /** 72 | * 在一个字符串source中搜索指定的字串find,并使用默认颜色设置前景色及背 73 | * 景色.以加亮效果,需要使用html格式才能显示出效果,主要用于匹配查询, 74 | * 该方法不区分大小写 75 | * @see #IgnoreCaseSearch(String, String, String, String) 76 | * @param source 原始字符串 77 | * @param find 要查找的字符 78 | * @return newStr 加了样式的新的字符串 79 | */ 80 | public static String IgnoreCaseSearch(String source, String find) { 81 | return IgnoreCaseSearch(source, find, null, null); 82 | } 83 | 84 | /** 85 | * 在一个字符串source中搜索指定的字串find,并使用color设置前景色及bgcolor设置背 86 | * 景色.需要使用html格式才能显示出效果,主要用于匹配查询,该方法不区分大小写 87 | * @param source 原始字符串 88 | * @param find 要查找的字符 89 | * @param color 找到后改变其前景色:格式如 red,blue,或 #FFFFFF 或null 90 | * @param bgcolor 找到后字串的背景色:格式如 red,blue,或 #FFFFFF 或null 91 | * @return newStr 加了样式的新的字符串 92 | */ 93 | public static String IgnoreCaseSearch(String source, String find, String color, String bgcolor) { 94 | String tColor = "red"; 95 | String tBgcolor = "yellow"; 96 | if (color != null) tColor = color; 97 | if (bgcolor != null) tBgcolor = bgcolor; 98 | String spanStart = ""; 99 | String spanEnd = ""; 100 | Pattern p = Pattern.compile(find, Pattern.CASE_INSENSITIVE); 101 | Matcher m = p.matcher(source); 102 | StringBuffer sb = new StringBuffer(); 103 | while (m.find()) { 104 | m.appendReplacement(sb, spanStart + m.group() + spanEnd); 105 | } 106 | m.appendTail(sb); 107 | return sb.toString(); 108 | } 109 | 110 | 111 | **截取字符串:** 112 | 113 | /** 114 | * 截取字符串 115 | * @param str 原始字符串 116 | * @param size 截取的长度 117 | * @return 新的字符串 118 | */ 119 | public static String subString(String str, int start, int size) { 120 | if (str.length() <= (start + size)) 121 | return str.substring(start); 122 | return str.substring(start, start + size); 123 | } 124 | 125 | **清除html标签:** 126 | 127 | /** 128 | * 清除Html标签 129 | * @param str 130 | * @return 131 | */ 132 | public static String clearHtml(String str) { 133 | int flag1 = str.indexOf("<"); 134 | int flag2 = str.indexOf(">"); 135 | String temp = null; 136 | while (flag1 != -1 || flag2 != -1) { 137 | str = clearHtmlPrivate(str); 138 | flag1 = str.indexOf("<"); 139 | flag2 = str.indexOf(">"); 140 | } 141 | return str; 142 | } 143 | 144 | private static String clearHtmlPrivate(String str) { 145 | int start = str.indexOf("<"); 146 | int end = str.indexOf(">"); 147 | if (start != -1 || end != -1) { 148 | str = str.substring(0, start) + str.substring(end + 1); 149 | } 150 | return str; 151 | } 152 | 153 | 154 | **根据给定的URL地址获取Html内容**: 155 | 156 | /** 157 | * 根据给定的URL地址获取Html内容 158 | * @param urlStr 159 | * @return 160 | */ 161 | public static String getHtmlCode(String url) throws MalformedURLException, IOException { 162 | StringBuilder sb = new StringBuilder(); 163 | URL u = new URL(url); 164 | InputStream in = u.openStream(); 165 | InputStreamReader isr = new InputStreamReader(in); 166 | char[] buff = new char[2048]; 167 | int len; 168 | while ((len = isr.read(buff, 0, buff.length))!= -1) { 169 | sb.append(buff, 0, len); 170 | } 171 | isr.close(); 172 | return sb.toString(); 173 | } -------------------------------------------------------------------------------- /设计模式.md: -------------------------------------------------------------------------------- 1 | ##设计模式 2 | 3 | 代码示例: 4 | 5 | [模板方法、工场模式、单例模式的综合应用](https://github.com/wswenyue/DesignPattern_Template_Single_Factory "模板方法、工场模式、单例模式的综合应用") 6 | 7 | [模板设计模式](https://github.com/wswenyue/DesignPattern_Template "模板设计模式") 8 | 9 | [适配器模式](https://github.com/wswenyue/DesignPattern_Adapter "适配器模式") 10 | 11 | ####单例设计模式 12 | >单例模式构造方法:1 构造函数private 2 创建本类对象(static) 3 提供一个方法给外界用来获取本类对象 13 | >>懒汉式 14 | >>饿汉式 15 | 16 | 实现步骤: 17 | 18 | 单例模式: 19 | 1)private 类名(){} 20 | 2) 21 | 懒汉式 22 | private static 类名 对象名 23 | 饿汉式(线程安全) 24 | private static 类名 对象名 = new 类名(); 25 | 3)public static 类名 getInstance(){ 26 | 懒汉式 27 | if(对象名==null) 28 | 对象名 = new 类名(); 29 | return 对象名; 30 | ---------------------------------------- 31 | 饿汉式 32 | return 对象名; 33 | } 34 | 35 | 36 | 代码实现 37 | 38 | class Demo08 39 | { 40 | /* 41 | 设计模式:单例 42 | 解决问题:一个类在内存中只有一个对象 43 | 1 构造方法私有化 44 | 2 构造方法私有化后,就一个对象都不能创建了,只能有该类自身提供对象 45 | 饿汉式:在声明类引用时实例化对象 46 | 懒汉式:在获取类的方法中先判断该对象是否为空,如果为空就实例化 47 | 3 提供让外界能够获得该对象的方法 48 | 49 | 懒汉式(线程不安全的) 50 | 饿汉式(线程安全的) 51 | */ 52 | public static void main(String[] args) 53 | { 54 | Single s1 = Single.getInstance(); 55 | Single s2 = Single.getInstance(); 56 | System.out.println(s1==s2); //比较的是地址 57 | 58 | Single2 s3 = Single2.getInstance(); 59 | Single2 s4 = Single2.getInstance(); 60 | System.out.println(s3==s4); 61 | } 62 | } 63 | //饿汉式 64 | class Single 65 | { 66 | 67 | //构造方法私有化:不能在本类的外部通过new创建对象 68 | private Single(){ 69 | 70 | } 71 | //定义一个本类的对象 72 | private static Single single = new Single(); 73 | 74 | //向外界提供可访问的方法,返回当前类的对象 75 | public static Single getInstance(){ 76 | return single; 77 | } 78 | } 79 | 80 | //懒汉式 81 | class Single2 82 | { 83 | private Single2(){} 84 | 85 | private static Single2 single ; 86 | 87 | public static Single2 getInstance(){ 88 | if(single == null) 89 | single = new Single2(); 90 | return single; 91 | } 92 | 93 | } 94 | 95 | --- 96 | 97 | #### 简单工厂模式 98 | >简单工厂:工厂生产父类产品,根据传递不同的参数,返回相应的子类产品对象 99 | 100 | 示例实现: 101 | 102 | import java.util.*; 103 | class Factory //厨房 104 | { 105 | public static IEat cook(int choose){ 106 | IEat i = null; 107 | switch(choose){ 108 | case 1: 109 | i = new Duck(); 110 | break; 111 | case 2: 112 | i = new Chicken(); 113 | break; 114 | case 3: 115 | i = new Fish(); 116 | break; 117 | case 4 : 118 | i = new Pig(); 119 | break; 120 | case 5: 121 | i = new Beef(); 122 | break; 123 | } 124 | return i; 125 | } 126 | 127 | //饭店入口 128 | public static void main(String[] args) 129 | { 130 | Scanner input = new Scanner(System.in); 131 | System.out.println("吃啥?1 烤鸭 2 炸鸡 3 水煮鱼 4 烤乳猪 5 烤牛排"); 132 | int choose = input.nextInt(); 133 | IEat i = Factory.cook(choose); 134 | i.eat(); 135 | System.out.println("欢迎下次光临!!!"); 136 | 137 | } 138 | } 139 | interface IEat 140 | { 141 | void eat(); //吃 142 | } 143 | class Duck implements IEat 144 | { 145 | public void eat(){ 146 | System.out.println("吃烤鸭"); 147 | } 148 | } 149 | class Chicken implements IEat 150 | { 151 | public void eat(){ 152 | System.out.println("吃炸鸡"); 153 | } 154 | } 155 | 156 | class Fish implements IEat 157 | { 158 | public void eat(){ 159 | System.out.println("吃水煮鱼"); 160 | } 161 | } 162 | class Pig implements IEat 163 | { 164 | public void eat(){ 165 | System.out.println("吃烤乳猪"); 166 | } 167 | } 168 | class Beef implements IEat 169 | { 170 | public void eat(){ 171 | System.out.println("吃牛排"); 172 | } 173 | } 174 | 175 | #### 模板设计模式 176 | 177 | 算法示例: 178 | 179 | class Demo12 180 | { 181 | /* 182 | 模板模式: 183 | 定义一个功能时,功能的一部分是确定的,而另一部分不确定。 184 | 确定的部分需要用到不确定的部分。 185 | 把不确定的部分暴露出去,让子类实现 186 | 187 | abstract class 类名{ 188 | //确定部分 189 | public void f(){ 190 | f1(); 191 | } 192 | //不确定部分 193 | public abstract void f1(); 194 | } 195 | */ 196 | public static void main(String[] args) 197 | { 198 | T t = new T(); 199 | t.getTime(); 200 | } 201 | } 202 | abstract class Test 203 | { 204 | //确定部分 205 | public void getTime(){ 206 | //开始时间:系统时间 207 | long start = System.currentTimeMillis(); 208 | f(); 209 | //结束时间 210 | long end = System.currentTimeMillis(); 211 | 212 | System.out.println("花费时间为:"+(end-start)+"ms"); 213 | 214 | } 215 | 216 | //不确定部分 217 | public abstract void f(); 218 | } 219 | 220 | class T extends Test 221 | { 222 | public void f(){ 223 | for(int i=1;i<50000;i++){ 224 | //System.out.println(""); 225 | } 226 | } 227 | } 228 | 229 | ----- 230 | ####装饰者模式 231 | 232 | 代码示例: 233 | 234 | package com.decorator; 235 | 236 | public class Demo { 237 | 238 | public static void main(String[] args) { 239 | Person p1 = new Zhansan(); 240 | p1.show(); 241 | 242 | Person p2 = new JeansDecorator(p1); 243 | p2.show(); 244 | 245 | Person p3 = new ShirtDecorator(p1); 246 | p3.show(); 247 | } 248 | } 249 | 250 | interface Person { 251 | void show();// 显示一个人 252 | } 253 | 254 | abstract class DecoratorPerson implements Person { 255 | private Person person; 256 | 257 | DecoratorPerson(Person person) { 258 | this.person = person; 259 | } 260 | } 261 | 262 | class JeansDecorator extends DecoratorPerson { 263 | 264 | JeansDecorator(Person person) { 265 | super(person); 266 | } 267 | 268 | @Override 269 | public void show() { 270 | System.out.println("穿牛仔裤的person"); 271 | 272 | } 273 | } 274 | 275 | class ShirtDecorator extends DecoratorPerson { 276 | 277 | ShirtDecorator(Person person) { 278 | super(person); 279 | } 280 | 281 | @Override 282 | public void show() { 283 | System.out.println("穿t恤的person"); 284 | 285 | } 286 | 287 | } 288 | 289 | class Zhansan implements Person { 290 | 291 | @Override 292 | public void show() { 293 | System.out.println("没有任何装饰的张三"); 294 | 295 | } 296 | 297 | } 298 | 299 | 模拟实现LineNumberReader的功能: 300 | 301 | package com.decorator; 302 | 303 | import java.io.FileReader; 304 | import java.io.IOException; 305 | import java.io.Reader; 306 | 307 | public class Demo { 308 | // LineNumberReader 装饰类,继承了BufferedReader 309 | public static void main(String[] args) throws IOException { 310 | FileReader fr = new FileReader("src/temp.txt"); 311 | 312 | MyLineNumberReader lnr = new MyLineNumberReader(fr); 313 | String line = null; 314 | 315 | while ((line = lnr.MyReadLine()) != null) { 316 | System.out.println(lnr.getLineNumber() + ":" + line); 317 | } 318 | lnr.myClose(); 319 | } 320 | 321 | } 322 | 323 | /* 封装MyLineNumber 324 | * setLineNumber():设置起始行号 325 | * 326 | * myReadLine():每次读取一行 327 | * 328 | * getLineNumber():获得当前行号 329 | */ 330 | class MyBufferedReader { 331 | private Reader r; // 真正读取功能的类 332 | private char[] arr = new char[512];// 相当于缓冲区 333 | private int index; // 数组下标 334 | private int count; // 统计缓冲区中字符个数 335 | 336 | public MyBufferedReader(Reader r) { 337 | this.r = r; 338 | } 339 | 340 | // 实现一次读取一个的功能 341 | public int myRead() throws IOException { 342 | // 缓冲区中是否有数据 343 | if (count == 0) { 344 | // 从文件中读取数据到缓冲区,返回值读取的字符数 345 | count = r.read(arr); 346 | index = 0; // 下标为0 347 | } 348 | if (count < 0) // 文件末尾 349 | return -1; 350 | // 从缓冲区中读取一个字符 351 | int num = arr[index]; 352 | index++;// 下标+1 353 | // 数量-1 354 | count--; 355 | return num; 356 | 357 | } 358 | 359 | // 一次读取一行 360 | public String myReadLine() throws IOException { 361 | StringBuilder sb = new StringBuilder(); 362 | int num; 363 | while ((num = myRead()) != -1) { 364 | if (num == '\r') 365 | continue; 366 | else if (num == '\n') 367 | return sb.toString(); 368 | else 369 | sb.append((char) num); 370 | } 371 | return null; 372 | } 373 | 374 | // 关闭流 375 | public void myClose() throws IOException { 376 | r.close(); 377 | } 378 | } 379 | 380 | class MyLineNumberReader extends MyBufferedReader { 381 | 382 | private int lineNumber; 383 | 384 | public MyLineNumberReader(Reader r) { 385 | super(r); 386 | } 387 | 388 | public void setLineNumber(int lineNumber) { 389 | this.lineNumber = lineNumber; 390 | } 391 | 392 | public int getLineNumber() { 393 | return this.lineNumber; 394 | } 395 | 396 | // 每次读取一行,行号+1 397 | public String MyReadLine() throws IOException { 398 | ++lineNumber; 399 | return super.myReadLine(); 400 | } 401 | 402 | } 403 | 404 | ---- 405 | 406 | #观察者模式 407 | **接口回调的实现** 408 | 409 | package com.wenyue.observe; 410 | 411 | /** 412 | * 413 | * Created by wswenyue on 2015/8/27. 414 | */ 415 | 416 | public class Test { 417 | public static void main(String[] args) { 418 | Person p = new Person("张三"); 419 | p.setPersonListener(new PersonListener() { 420 | @Override 421 | public void doEat(Event e) { 422 | Person person = e.getSouce(); 423 | System.out.println(person.getName() + "吃东西..."); 424 | } 425 | 426 | @Override 427 | public void doReading(Event e) { 428 | Person person = e.getSouce(); 429 | System.out.println(person.getName() + "正在读书..."); 430 | 431 | } 432 | }); 433 | 434 | p.read(); 435 | p.eat(); 436 | 437 | } 438 | 439 | } 440 | 441 | /** 442 | * 观察者模式 443 | * 接口回调 444 | */ 445 | class Person { 446 | private String name; 447 | private PersonListener listener; 448 | 449 | public Person() { 450 | } 451 | 452 | public String getName() { 453 | return name; 454 | } 455 | 456 | public void setName(String name) { 457 | this.name = name; 458 | } 459 | 460 | public Person(String name) { 461 | this.name = name; 462 | } 463 | 464 | public void setPersonListener(PersonListener listener) { 465 | this.listener = listener; 466 | } 467 | 468 | public void eat() { 469 | if (listener != null) { 470 | listener.doEat(new Event(this)); 471 | } 472 | } 473 | 474 | public void read() { 475 | if (listener != null) { 476 | listener.doReading(new Event(this)); 477 | } 478 | } 479 | 480 | 481 | } 482 | 483 | /** 484 | * 监听器接口 485 | */ 486 | interface PersonListener { 487 | void doEat(Event e); 488 | 489 | void doReading(Event e); 490 | } 491 | 492 | /** 493 | * 事件源 494 | */ 495 | class Event { 496 | Person souce; 497 | 498 | public Person getSouce() { 499 | return souce; 500 | } 501 | 502 | public void setSouce(Person souce) { 503 | this.souce = souce; 504 | } 505 | 506 | public Event() { 507 | 508 | } 509 | 510 | public Event(Person souce) { 511 | 512 | this.souce = souce; 513 | } 514 | } -------------------------------------------------------------------------------- /调用图解.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wswenyue/note/a7df9fc77f72331270f228576a056501c0d06ba6/调用图解.PNG --------------------------------------------------------------------------------