android 笔记

依赖关系在 build.gradle 中的 配置 (在具体的项目文件夹)

# application
	程序初始化 重写 Application 
	在 AndroidManifest 中的 <application android:name=".your app" ... 注册
	可以实现一些APP启动时候的操作

# 视图 View
	view 对象就是一个透明的块,可直接用
	视图常量 ViewConfiguration 
	当前视图常量 如滚动条的宽度,BAR的高度等 通过 ViewConfiguration.get(Context) 获得
	ViewGroup 是从view继承的
	ImageView 只支持 本地资源或代码资源,
	ImageLoader:
		网络图片资源用外部库 ImageLoader.getInstance() 或建线程加载后填充
		ImageLoader 的 gradle 为 compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.4'
	fresco:	 支持圆角 加载自定义 保存宽高比
		gradle 为 compile 'com.facebook.fresco:fresco:0.6.0+'
		XML 为:
		<com.facebook.drawee.view.SimpleDraweeView
			android:id="@+id/img"
			android:layout_width="100dp"
			android:layout_height="wrap_content"
			fresco:placeholderImage="@drawable/aa"
			fresco:viewAspectRatio="2"
			fresco:roundedCornerRadius="10dp"
			/>
		 代码:
		 初始化:  Fresco.initialize(this);
		 Uri uri = Uri.parse(/*http://xxxx.jpg*/);
		 SimpleDraweeView draweeView = (SimpleDraweeView) view.findViewById(R.id.img);
		 draweeView.setImageURI(uri);
		 
	glide
		gradle 为
			compile 'com.github.bumptech.glide:glide:3.6.1'
			compile 'com.android.support:support-v4:19.1.0'
		无需初始化 支持GIF 圆角通过 transform() 实现或 compile 'de.hdodenhof:circleimageview:1.3.0'  实现
		ImageView imageView = (ImageView) findViewById(R.id.my_image_view);
		Glide.with(this).load("http://goo.gl/gEgYUd").into(imageView);
		
	Picasso:
		compile 'com.squareup.picasso:picasso:2.5.2'
		无需初始化 圆角通过 transform() 实现或 compile 'de.hdodenhof:circleimageview:1.3.0'  实现
		Picasso.with(context)
				.load(R.drawable.landing_screen)
				.placeholder(R.id.progressBarDetails)
                .error(R.drawable.friend_request)
				.into(imageView1);
		Picasso.with(context).load("file:///android_asset/DvpvklR.png").into(imageView2);
		Picasso.with(context).load(new File(...)).into(imageView3);
		//自定义下载
		Picasso picasso = new Picasso.Builder(myslideAcitivty.this).downloader(
			//OkHttpDownloader
			//UrlConnectionDownloader
			new OkHttpDownloader(new File(imageCacheDir))
		).build();
	
	ImageView 宽高比 https://github.com/hongyangAndroid/android-percent-support-extend
	
	视图在 onCreate onStart 等方法中未渲染,高宽为0 需要高宽请重写 onWindowFocusChanged 设置
	示例:
		@Override //重设margin
		public void onWindowFocusChanged(boolean hasFocus) {
			super.onWindowFocusChanged(hasFocus);
			AppBarLayout abl = (AppBarLayout) findViewById(R.id.app_bar_layout);
			LinearLayout ll = (LinearLayout) findViewById(R.id.linearLayout);
			ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams)ll.getLayoutParams();
			layoutParams.topMargin=abl.getHeight();
			ll.setLayoutParams(layoutParams);
		}
		
	设置布局:setLayoutParams 为父布局类型
		LinearLayout LayoutHead = (LinearLayout)findViewById(R.id.layline);
    	Button DateButton = (Button)findViewById(R.id.but);
		//LinearLayout.LayoutParams ly=DateButton.getLayoutParams(); //ly may be null
		//ly.width=100;
		//DateButton.setLayoutParams(ly);
		//OR 
        DateButton.setLayoutParams(
			new LinearLayout.LayoutParams(
				LinearLayout.LayoutParams.MATCH_PARENT,
                LinearLayout.LayoutParams.WRAP_CONTENT)
		);
        layoutHead.addView(DateButton);
	
	动态加ID:
		idx.xml
			<resources>
				<item type="id" name="return_scan_result"/>
			</resources>
		代码:
			TextView tt = new TextView(this);
			tt.setId(R.id.return_scan_result);
	
	窗口管理,屏幕高宽等
		Display display = getWindowManager().getDefaultDisplay();
		Point size = new Point();
		display.getSize(size);
		int width = size.x;
		int height = size.y;
	
	获取 基本组件可以通过 ComponentName 来获取,支持Context 中获取指定的view组件 
	示例
		new ComponentName(context, myreceiver.class);
		new ComponentName("包名","类或类名")
		
	加载提示
		final ProgressDialog dialog = new ProgressDialog(this);
        dialog.setMessage("加载中");
        dialog.show();
		
	用在非本身的视图 RemoteViews 
		new RemoteViews(context.getPackageName(), R.layout.aa);
		
	排版页面时,样式可独立到style中,通过style来引用 (类似CSS) style 通过 parent实现继承
	
	自定义视图,继承至view 示例
		定义 view
			public class MyView extends View {
				private Paint mPaint;
				private int textColor;
				public MyView(Context context) {
					super(context);
					mPaint = new Paint();
				}
				public MyView(Context context, AttributeSet attrs) {
					super(context, attrs);
					//自定义属性 参考/values/attrs.xml
					TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyView);
					textColor = a.getColor(R.styleable.MyView_bgcolor, 0XFFFFFFFF);
					float textSize = a.getDimension(R.styleable.MyView_textSize, 36);
					a.recycle();
					mPaint = new Paint();
					mPaint.setTextSize(textSize);
					mPaint.setColor(textColor);
				}
				@Override
				protected void onDraw(Canvas canvas) {
					super.onDraw(canvas);
					mPaint.setStyle(Paint.Style.FILL);
					canvas.drawRect(new Rect(10, 10, 100, 100), mPaint);
					mPaint.setColor(textColor);
				}
				@Override //可不重写此方法
				protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
					//设置自己的高宽
					super.onMeasure(widthMeasureSpec, heightMeasureSpec);
					//父元素推荐宽高
				   // int w = MeasureSpec.getSize(widthMeasureSpec);
				  //  int h = MeasureSpec.getSize(heightMeasureSpec);
					//当前元素的模式
				  //  int wMode = MeasureSpec.getMode(widthMeasureSpec);
				  //  int hMode = MeasureSpec.getMode(heightMeasureSpec);
					//MeasureSpec.AT_MOST //元素的宽高超过此值将不可见
					//MeasureSpec.EXACTLY //元素已指定宽或高
					//MeasureSpec.UNSPECIFIED //其他
					//告知父元素本身高宽
				  //  setMeasuredDimension(w, h);
				}
			}
		定义 /values/attrs.xml
			<?xml version="1.0" encoding="utf-8"?>
			<resources>
				<!--name 为自定义视图类名-->
				<declare-styleable name="MyView">
					<!-- color:颜色值 -->
					<attr name="bgcolor" format="color" />
					<!-- reference:参考某一资源ID 多种类型用|分割 -->
					<attr name="backgroupd" format="reference|color" />
					<!-- fraction:表示百分比 -->
					<attr name = "pivotX" format = "fraction" />
					<!-- string:表示字符串 -->
					<attr name = "apiKey" format = "string" />
					<!-- integer:表示整形 -->
					<attr name = "count" format="integer" />
					<!-- float:表示浮点数 -->
					<attr name = "namefloat" format = "float" />
					<!-- dimension:表示尺寸 -->
					<attr name = "namedimension" format = "dimension" />
					<!-- dimension:表示布尔 -->
					<attr name = "nameboolean" format = "boolean" />
					<!-- flag TAG:表示可以进行位运算 使用 mode1|mode2 -->
					<attr name="mode">
						<flag name = "mode1" value = "0" />
						<flag name = "mode2" value = "1" />
					</attr>
					<!-- enum TAG:选择其中一个 -->
					<attr name="orientation">
						<enum name="horizontal" value="0" />
						<enum name="vertical" value="1" />
					</attr>
					<attr name="textSize" format="dimension" />
				</declare-styleable>
			</resources>
		使用自定义view
			 <LinearLayout
				android:layout_width="wrap_content"
				android:layout_height="wrap_content"
				xmlns:custom="http://schemas.android.com/apk/res-auto"
				>
				<com.example.dome1.MyView
					custom:bgcolor="#000000"
					android:layout_width="wrap_content"
					android:layout_height="wrap_content"
					/>
			</LinearLayout>
			
	自定义视图组
		public class myviewgroup extends ViewGroup {
			public ccimg(Context context) {
				super(context);
			}
			public ccimg(Context context, AttributeSet attrs) {
				super(context, attrs);
				//设置属性
		//        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyView);
		//        textColor = a.getColor(R.styleable.MyView_bgcolor, 0XFFFFFFFF);
		//        float textSize = a.getDimension(R.styleable.MyView_textSize, 36);
		//        a.recycle();
		//        mPaint = new Paint();
		//        mPaint.setTextSize(textSize);
		//        mPaint.setColor(textColor);
			}
			@Override
			protected void onDraw(Canvas canvas) {
				super.onDraw(canvas);
				//绘制自己的内容
			}
			@Override
			protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
				// 设置子视图
				int padding=20,
					wh=100;
				for (int i = 0, size = getChildCount(); i < size; i++) {
					View view = getChildAt(i);
					// 放置子View,宽高都是100
					view.layout(left, top, left + wh, top + wh);
					left += wh + padding;
				}
			}
			@Override
			protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
				//设置自己的高宽
				super.onMeasure(widthMeasureSpec, heightMeasureSpec);
				//getMeasuredWidth() //运算得到实际内容宽度
				//getMeasuredHeight() //运算得到实际内容高度
				//父元素推荐宽高
			   // int w = MeasureSpec.getSize(widthMeasureSpec);
			  //  int h = MeasureSpec.getSize(heightMeasureSpec);
				//当前元素的模式
			  //  int wMode = MeasureSpec.getMode(widthMeasureSpec);
			  //  int hMode = MeasureSpec.getMode(heightMeasureSpec);
				//MeasureSpec.AT_MOST //元素的宽高超过此值将不可见
				//MeasureSpec.EXACTLY //元素已指定宽或高
				//MeasureSpec.UNSPECIFIED //其他
				//告知父元素本身高宽
			  //  setMeasuredDimension(w, h);
			}
		}
		
	弹出窗口
		1. 对话框 Dialog 子类
			一般对话框可以直接用 AlertDialog.Builder alert= new AlertDialog.Builder(this);
			或者重写 AlertDialog 类实现一些自己的弹框提示 示例:
				AlertDialog.Builder alert = new AlertDialog.Builder(TouchActivity.this);
				alert.setTitle("Alert");
				alert.setMessage("messgae");
				alert.show();
			或继承 dialog 示例:
				 public class MyCustomDialog extends Dialog {
					public MyCustomDialog(Context context) {
						super(context);
					}
					@Override
					protected void onCreate(Bundle savedInstanceState) {
						super.onCreate(savedInstanceState);
						setContentView(R.layout.xxx);
						//设置标题
						setTitle("this is title");
						Button clickBtn = (Button) findViewById(R.id.button);
						clickBtn.setOnClickListener(new View.OnClickListener() {
							@Override
							public void onClick(View v) {
								MyCustomDialog.this.dismiss();
							}
						});
					}
				}
				
				
		2. 使用 Activity 加样式 
			样式:
				<style name="MyDialogStyle">
					<item name="android:windowBackground">@android:color/transparent</item>
					<item name="android:windowFrame">@null</item>
					<item name="android:windowNoTitle">true</item>
					<item name="android:windowIsFloating">true</item>
					<item name="android:windowIsTranslucent">true</item>
					<item name="android:windowContentOverlay">@null</item>
					<item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
					<item name="android:backgroundDimEnabled">true</item>
				</style>
			在 AndroidManifest.xml 注册
				<activity android:name=".tabactivity" android:theme="@style/MyDialogStyle"></activity>
			使用:
				Intent i= new Intent(MainActivity.this,tabactivity.class);
                startActivityForResult(i);
				
		3. 使用 PopupWindow 类 示例:
			 //选择布局填充视图
			View contentView = LayoutInflater.from(MainActivity.this).inflate(
					R.layout.tab, null);
			Button button = (Button) contentView.findViewById(R.id.button3);
			//创建弹出窗口
			final PopupWindow popupWindow = new PopupWindow(contentView,
					LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT, true);
			button.setOnClickListener(new View.OnClickListener() {
				@Override
				public void onClick(View v) {
					popupWindow.dismiss();//关闭
				}
			});
			popupWindow.setTouchable(true);
			popupWindow.setTouchInterceptor(new View.OnTouchListener() {
				@Override
				public boolean onTouch(View v, MotionEvent event) {
					return false;
				}
			});
			popupWindow.setBackgroundDrawable(getDrawable(R.drawable.a));
			popupWindow.showAsDropDown(contentView);

# 运行时授权 
	要添加在 AndroidManifest.xml 添加 uses-permission
	 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if(Build.VERSION.SDK_INT>=23) {
            //单个
            int hasWriteContactsPermission = checkSelfPermission(Manifest.permission.CAMERA);
            if (hasWriteContactsPermission != PackageManager.PERMISSION_GRANTED) {
                if (!shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)) {
					//false 表示授权拒绝
                    Log.i("xxx", "auth bad 4");
                }else{
                    requestPermissions(new String[]{Manifest.permission.CAMERA},222);
                }
            }else{
                Log.i("xxx", "auth ok 2");
            }
            //多个
            final List permissionsNeeded = new ArrayList();
            final List<String> permissionsList = new ArrayList<String>();
            if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                permissionsList.add(Manifest.permission.ACCESS_FINE_LOCATION);
                // Check for Rationale Option
                if (!shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)) {
                    //false 表示授权拒绝
                    permissionsNeeded.add("need location");
                }
            }
            if (checkSelfPermission(Manifest.permission.WRITE_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
                permissionsList.add(Manifest.permission.WRITE_CONTACTS);
                // Check for Rationale Option
                if (!shouldShowRequestPermissionRationale(Manifest.permission.WRITE_CONTACTS)) {
                    //false 表示授权拒绝
                    permissionsNeeded.add("need contats");
                }
            }
            if (permissionsList.size() > 0) {
                if (permissionsNeeded.size() > 0) {
                    Log.i("xxx", "auth bad 1");
                }
                requestPermissions(permissionsList.toArray(new String[permissionsList.size()]), 111);
            }else{
                Log.i("xxx", "auth ok 3");
            }
        }
    }
    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        switch (requestCode) {
            case 111:
                Map<String, Integer> perms = new HashMap<String, Integer>();
                // Initial
                perms.put(Manifest.permission.WRITE_CONTACTS, PackageManager.PERMISSION_GRANTED);
                perms.put(Manifest.permission.ACCESS_FINE_LOCATION, PackageManager.PERMISSION_GRANTED);
                // Fill with results
                for (int i = 0; i < permissions.length; i++  )
                    perms.put(permissions[i], grantResults[i]);
                // Check for ACCESS_FINE_LOCATION
                if (perms.get(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
                        && perms.get(Manifest.permission.WRITE_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
                    Log.i("xxx","auth ok 4");
                } else {
                    Log.i("xxx","auth bad 2");
                }
            break;
            case 222:
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    Log.i("xxx","auth ok 1");
                } else {
                    Log.i("xxx","auth bad 3");
                }
            break;
            default:
                super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        }
    }
			
# 视图坐标
	获取屏幕区域的宽高等尺寸获取
		DisplayMetrics metrics = new DisplayMetrics();
		getWindowManager().getDefaultDisplay().getMetrics(metrics);
		int widthPixels = metrics.widthPixels;
		int heightPixels = metrics.heightPixels;
	
	应用程序App区域宽高等尺寸获取
		Rect rect = new Rect();
		getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
	
	获取状态栏高度
		Rect rect= new Rect();
		getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
		int statusBarHeight = rectangle.top;
	
	View布局区域宽高等尺寸获取
		Rect rect = new Rect();  
		getWindow().findViewById(Window.ID_ANDROID_CONTENT).getDrawingRect(rect);  

	View的静态坐标方法
		getScrollY() 返回View竖向滚动距离
		getScrollX() 返回View横向滚动距离
		getLeft()	返回View自身左边到父布局左边的距离
		getTop()	返回View自身顶边到父布局顶边的距离
		getRight()	返回View自身右边到父布局左边的距离
		getBottom()	返回View自身底边到父布局顶边的距离
		getX()	返回值为getLeft()+getTranslationX(),当setTranslationX()时getLeft()不变,getX()变。
		getY()	返回值为getTop()+getTranslationY(),当setTranslationY()时getTop()不变,getY()变。	
	
	MotionEvent坐标方法
		getX()	当前触摸事件距离当前View左边的距离
		getY()	当前触摸事件距离当前View顶边的距离
		getRawX()	当前触摸事件距离整个屏幕左边的距离
		getRawY()	当前触摸事件距离整个屏幕顶边的距离
	
	View宽高方法
		getWidth()	layout后有效,返回值是mRight-mLeft,一般会参考measure的宽度(measure可能没用),但不是必须的。
		getHeight()	layout后有效,返回值是mBottom-mTop,一般会参考measure的高度(measure可能没用),但不是必须的。
		getMeasuredWidth()	返回measure过程得到的mMeasuredWidth值,供layout参考,或许没用。
		getMeasuredHeight()	返回measure过程得到的mMeasuredHeight值,供layout参考,或许没用。
	
	View的方法
	getLocalVisibleRect()	
		获取View自身可见的坐标区域,坐标以(0,0)开始,另一点为可见区域右下角相对自己(0,0)点的坐标
		例子:(0, 0 - 410, 100)
	getGlobalVisibleRect()
		获取View在屏幕绝对坐标系中的可视区域,坐标以原点开始的坐标,另一点为可见区域右下角原点的坐标
		例子:(30, 100)	(30, 250)
	getLocationOnScreen()
		坐标是相对整个屏幕而言,Y坐标为View左上角到屏幕顶部的距离。
	getLocationInWindow()		
		如果为普通Activity则Y坐标为View左上角到屏幕顶部(此时Window与屏幕一样大);如果为对话框式的Activity则Y坐标为当前Dialog模式Activity的标题栏顶部到View左上角的距离。
		
	View的滑动方法
		offsetLeftAndRight(int offset)	水平方向挪动View,offset为正则x轴正向移动,移动的是整个View,getLeft()会变的,自定义View很有用。
		offsetTopAndBottom(int offset)	垂直方向挪动View,offset为正则y轴正向移动,移动的是整个View,getTop()会变的,自定义View很有用。
		scrollTo(int x, int y)	将View中内容(不是整个View)滑动到相应的位置,参考坐标原点为ParentView左上角,x,y为正则向xy轴反方向移动,反之同理。
		scrollBy(int x, int y)	在scrollTo()的基础上继续滑动xy。
		setScrollX(int value)	实质为scrollTo(),只是只改变Y轴滑动。
		setScrollY(int value)	实质为scrollTo(),只是只改变X轴滑动。
		getScrollX()/getScrollY()	获取当前滑动位置偏移量。


# 组件调用 Intent

	1. 隐式添加
		向系统注册静态 Intent 在 AndroidManifest 加 intent-filter
			<activity
				android:name=".activity.MyActivity"
				android:label="@string/ac_name_image_list" >
				<intent-filter>
					<action android:name="mxp"/>
					<category android:name="android.intent.category.DEFAULT" />
				</intent-filter>
			</activity>
		在 MyActivity 添加  public static final String MY_ACTION = "mxp";
		启动: startActivity(new Intent(MyActivity.MY_ACTION));
		关于 category 匹配
			如下 AndroidManifest
			<intent-filter>  
                <action android:name="action1" />
                <category android:name="cate1"/>
                <category android:name="android.intent.category.DEFAULT" />  
            </intent-filter>
			启动 
			Intent intent = new Intent("action1");
			intent.addCategory("cate1");//有无都匹配
			startActivity(intent);
		关于 data 匹配
			如下 AndroidManifest
			 <intent-filter>
                <action android:name="action1" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:scheme="file" />
                <data android:mimeType="audio/*" />
                <data android:pathPattern=".*.mp3" /><!-路径匹配->
            </intent-filter>
			启动 
			Uri uri=Uri.parse("file://aaaa.mp3");
			Intent intent = new Intent("action1");
			intent.setData(uri);
			startActivity(intent);
		
	2. 基本组件通过Intent来相互调用  setExtras getExtras 参数传递
	
	3. PendingIntent
		包装Intent,使Intent延时触发,有以下类型
		PendingIntent.getBroadcast()
		PendingIntent.getActivity() & PendingIntent.getActivities()
		PendingIntent.getService()
		
	4. 可通过 ComponentName 进行调用
		Intent it=new Intent();
        it.setComponent(new ComponentName(getPackageName(),MyActivity.class.getName()));
        startActivity(it)

	
			
			

# 加载管理 Loader
	
	CursorLoader 使用示例,一般使用在 Cursor 数据源下
		public static class CursorLoaderListFragment extends ListFragment
				implements LoaderManager.LoaderCallbacks<Cursor> {
			SimpleCursorAdapter mAdapter;
			@Override
			public void onActivityCreated(Bundle savedInstanceState) {
				super.onActivityCreated(savedInstanceState);
				mAdapter = new SimpleCursorAdapter(getActivity(),
						android.R.layout.simple_list_item_2, null,
						new String[] { ContactsContract.Contacts.DISPLAY_NAME, ContactsContract.Contacts.CONTACT_STATUS },
						new int[] { android.R.id.text1, android.R.id.text2 }, 0);
				setListAdapter(mAdapter);
				getLoaderManager().initLoader(0, null, this);
			}
			static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] {
					ContactsContract.Contacts._ID,
					ContactsContract.Contacts.DISPLAY_NAME,
					ContactsContract.Contacts.CONTACT_STATUS,
					ContactsContract.Contacts.CONTACT_PRESENCE,
					ContactsContract.Contacts.PHOTO_ID,
					ContactsContract.Contacts.LOOKUP_KEY,
			};
			public Loader<Cursor> onCreateLoader(int id, Bundle args) {
				Uri baseUri;
				baseUri = ContactsContract.Contacts.CONTENT_URI;
				String select = "";
				//返回游标Loader
				return new CursorLoader(getActivity(), baseUri,
						CONTACTS_SUMMARY_PROJECTION, select, null,
						ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");
			}
			public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
				//加载完成回调,重设游标
				mAdapter.swapCursor(data);
				// The list should now be shown.
				if (isResumed()) {
					setListShown(true);
				} else {
					setListShownNoAnimation(true);
				}
			}
			public void onLoaderReset(Loader<Cursor> loader) {
				//重设
				mAdapter.swapCursor(null);
			}
		}
		
	AsyncTaskLoader 使用示例,一般用在数据加载,如列表等, 
	如 Activity 里多个 Fragment 时候 方便管理,只有简单数据加载 可直接用 封装AsyncTask 
		class  myloader extends AsyncTaskLoader<List<String>>{
			Bundle args;
			public myloader(Context context, Bundle args) {
				super(context);
				this.args=args;
			}
			@Override
			public List<String> loadInBackground() {
				// 根据 this.args 不同进行处理
				Log.i("myout","out");
				List<String> my= new ArrayList<String>();
				my.add("hi");
				return my;
			}
			@Override
			public void cancelLoadInBackground() {
				//当发生取消时候调用.如请求服务器数据.这里进行取消操作
			}
			@Override
			protected void onStartLoading() {
				forceLoad();
			}
			@Override
			protected void onStopLoading() {
				cancelLoad();
			}
			@Override
			protected void onReset() {
				super.onReset();
				onStopLoading();
			}
		}
		使用AsyncTask
		final ListView lv= (ListView)findViewById(R.id.listView);
        final ArrayAdapter apt=new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,android.R.id.text1);
        lv.setAdapter(apt);
		final LoaderManager.LoaderCallbacks loadercallback = new LoaderManager.LoaderCallbacks<List<Map<String,String>>>(){
            @Override
            public Loader<List<Map<String,String>>> onCreateLoader(int id, Bundle args) {
                return new myloader(MainActivity.this,args);
            }
            @Override
            public void onLoadFinished(Loader<List<Map<String,String>>> loader, List<Map<String,String>> data) {
                apt.addAll(data);
                //加载完成,进行其他视图更新
            }
            @Override
            public void onLoaderReset(Loader<List<Map<String,String>>> loader) {
				//当调用 getLoaderManager().destroyLoader(1);
                apt.clear();
				//进行视图清空处理等
            }
        };
		//初始化加载
        getLoaderManager().initLoader(1, null, loadercallback);
		//重新加载数据
		getLoaderManager().destroyLoader(1);
		getLoaderManager().initLoader(1, null, loadercallback);
		//重新启动加载器(非重新加载数据,如需要加载下一页数据)
		getLoaderManager().restartLoader(1,b,loadercallback);
		

# 页面 Activity

	R.drawable 图片资源 
	R.string 字符资源
	R.menu 菜单 比较特殊的一个View 菜单填充用 MenuInflater
		示例:
			xml:
			<menu xmlns:android="http://schemas.android.com/apk/res/android" >
				<item
					android:id="@+id/share_item"
					android:orderInCategory="100"
					app:showAsAction="always"
					android:title="分享"
					/>
			</menu>
		添加及监听:
			@Override
			public boolean onCreateOptionsMenu(Menu menu) {
				getMenuInflater().inflate(R.menu.my,menu);
				return super.onCreateOptionsMenu(menu);
			}
			@Override
			public boolean onOptionsItemSelected(MenuItem item) {
				switch (item.getItemId()) {
					case R.id.share_item:
						break;
				}
				return super.onOptionsItemSelected(item);
			}
			
	资源 assets 通过 getAssets().open() 来访问
	
	资源 Resources 通过 get** 系列获取函数 如getDrawable(R.drawable.a1); 获得 drawable 对象
	
		
	填充获取布局View (注意:获取到后未添加到显示视图中)
		getLayoutInflater().inflate(R.layout.activity_touch, null);
        ((LayoutInflater){Context}.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.activity_touch, null);
	
	ViewGroup 下 Layout 用来布局页面	
		LayoutInflater 处理layout XML 资源 返回View
	R.id 在ids.xml有部分预设ID,在android.R.id 下 如content为当前视图根节点
		ViewGroup rootnode = (ViewGroup)findViewById(android.R.id.content);//根节点
	遍历ViewGroup的子视图
		ViewGroup viewById = (ViewGroup)findViewById(android.R.id.content);
        for (int i=0;i<viewById.getChildCount();i++)
        viewById.getChildAt(i);
	
	添加视图(ViteGroup对象可用)
		TextView t=new TextView(this);
        t.setText("fsadf");
        rootnode.addView(t);
		
	片段 Fragment 及管理 可添加,替换等 (未显示的页面) (XML不能是空的Fragment)
		填充 附属至相应的Activity生效
		通过getView() 处理里面的view
		FragmentActivity 提供辅助 Fragment 的方法
		示例代码
			代码方式添加
			public static class PlaceholderFragment extends Fragment {
				public PlaceholderFragment() {
				}
				@Override
				public View onCreateView(LayoutInflater inflater, ViewGroup container,
						Bundle savedInstanceState) {
					View rootView = inflater.inflate(R.layout.fragment_main, container,
							false);
					return rootView;
				}
			}
			添加进显示
			if (savedInstanceState == null) {
				getFragmentManager().beginTransaction()
					.add(R.id.container, new PlaceholderFragment()).commit();
			}
			//添加但不显示
			getFragmentManager().beginTransaction().add(ttt, "ttt").commit();
			//获取
			Fragment ttt = getFragmentManager().findFragmentByTag("ttt");
			
		XML 方式添加 (必须要有id属性)
			<fragment 
				android:id="@+id/id_fragment_title"
				android:name="com.example.xxx.MainActivity$PlaceholderFragment"
				android:layout_width="match_parent"
				android:layout_height="match_parent"
			 />
			通过 setContentView(R.layout.activity_main);
	
		
	数据传递
		设置
			Intent intent = new Intent("action1");
			intent.putExtra("test","xxx");
			startActivity(intent);
		获取 get...Extra 系列方法
			getIntent().getStringExtra("test");
		通过Uri 的数据
			Uri uri=getIntent().getData();
		跳转返回
			//起始 Activity: 1->requestCode
			{...
			Intent intent=new Intent("action1");
			startActivityForResult(intent, 1);
			...}
			@Override
			rotected void onActivityResult(int requestCode, int resultCode, Intent data) {
				super.onActivityResult(requestCode, resultCode, data);
				switch(requestCode){
					case 1:
						switch(resultCode){
							case 1:
								//处理数据
							break;
						}
					break;
				}
			}
			//数据 Activity: 1->resultCode
			setResult(1, intent);
			finish();
		于 Fragment 的数据传递
			Activity 设置数据
			PlaceholderFragment my = new PlaceholderFragment();
			Bundle bundle = new Bundle();
			bundle.putString("test","test");
			my.setArguments(bundle);
			在 PlaceholderFragment 的 onCreateView 中获取
			Bundle arguments = my.getArguments();
			


			

# 数据适配器
	1. 视图分配
		a. 重写 Adapter 的getView
		b. setViewBinder 重写 ViewBinder的setViewValue方法
		
	2. BaseAdapter 基本适配器
		完全自主 适配器基类 数据源可不定格式
		
	3. SimpleAdapter 简单适配器 (简单键值对数据)
		格式:Context context, List<? extends Map<String, ?>> data,
			int resource, String[] from, int[] to
			
		提供数据(MAP LIST) 布局 数据格式 布局元素
		根据提供的格式渲染
		示例:
			List<Map<String,String>> list= new ArrayList<Map<String, String>>();
			Map<String,String> m1= new HashMap<String,String>();
			m1.put("aa","aaa");
			m1.put("bb", "bbb");
			list.add(m1);
			SimpleAdapter sa= new SimpleAdapter(this,list,R.layout.text,
				new String[]{"aa","bb"},new int[]{R.id.aa,R.id.bb});
				
	4. ArrayAdapter<T> 数组适配器 (类型固定,非简单键值对,如建模的对象,或String)
		a. 简单String
		示例:
			ArrayAdapter aa=new ArrayAdapter<String>(this,R.layout.text,R.id.aa);
			aa.add("sssssssssssss");
			
		b. 指定类类型 一般需重写:视图分配
		
	5. CursorAdapter 游标适配器
		一般用于通过 Content Provider 的数据,如果联系人,本地数据库等
		示例:
			Cursor curContacts=getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,new String[]{
				ContactsContract.Contacts._ID,
				ContactsContract.Contacts.DISPLAY_NAME,
				ContactsContract.Contacts.HAS_PHONE_NUMBER,
				ContactsContract.Contacts.LOOKUP_KEY}, null, null, null);
			CursorAdapter aa = new MyCursorAdapter(this,curContacts);
			//重写 newView bindView 方法实现视图
			class MyCursorAdapter extends CursorAdapter {
				public MyCursorAdapter(Context context, Cursor c) {
					super(context, c,true);
				}
				public View newView(Context context, Cursor cursor, ViewGroup parent) {
					LayoutInflater vi = null;
					vi = getLayoutInflater();
					View v=vi.inflate(R.layout.text, parent, false);
					TextView view = (TextView)v.findViewById(R.id.aa);
					return view;
				}
				@Override
				public void bindView(View v, Context context, Cursor cursor) {
					TextView nameView = (TextView)v.findViewById(R.id.aa);
					nameView.setText(cursor
							.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)));
				}
			}
			
	6.? ResourceCursorAdapter & SimpleCursorAdapter 对 CursorAdapter 的再次封装
		其中 SimpleCursorAdapter 实现了类似于 SimpleAdapter 的封装
		示例:
			Cursor curContacts=getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,new String[]{
					ContactsContract.Contacts._ID,
					ContactsContract.Contacts.DISPLAY_NAME,
					ContactsContract.Contacts.HAS_PHONE_NUMBER,
					ContactsContract.Contacts.LOOKUP_KEY}, null, null, null);
			lv.setAdapter(new SimpleCursorAdapter(this,R.layout.text,curContacts,new String[]{
					ContactsContract.Contacts.DISPLAY_NAME, ContactsContract.Contacts.HAS_PHONE_NUMBER
			},new int[]{
					R.id.aa,R.id.bb
			},CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER));
			
	7. 数据修改 
		a. 数据源变动 适配器的数据为初始化时候的源,或通过适配器修改数据,将会自动反应到视图
		2. 视图数据变动 修改视图后,调用适配器的 notifyDataSetChanged 方法,将会把视图数据反应到数据源


	
# 异步执行与数据交互
	1. 请求线程创建
		1. 手动创建线程
			 final Handler h = new Handler(){
				@Override
				public void handleMessage(Message msg) {
					super.handleMessage(msg);
					Bundle b= msg.getData();
					//视图线程,处理视图
				}
			};
			new Thread(){
				@Override
				public void run() {
					//请求数据等...
					Message msg= new Message();
					Bundle b=new Bundle();
					//设置数据
					msg.setData(b);
					h.sendMessage(msg);
					super.run();
				}
			}.start();
			
		2. 使用AsyncTask
			//AsyncTask 类型: 根据需要传递
			// 请求参数,进度参数,执行完返回结果
			private class MyTask extends AsyncTask<String, Integer, String> {
				@Override
				protected void onPreExecute() {
					//请求前调用,可处理UI
				}
				@Override
				protected String doInBackground(String... params) {
					//处理请求等操作,请求线程,不处理UI
					//setProgress();操作进度
					return null;
				}
				@Override
				protected void onProgressUpdate(Integer... progresses) {
				   //进度操作,处理UI
				}
				@Override
				protected void onPostExecute(String result) {
					//执行完操作.处理UI
				}
				@Override
				protected void onCancelled() {
					//用户取消操作,处理UI
				}
			}
			调用:
			new MyTask().execute("/*request prams*/");
		
	2. 请求方式
		a. 使用OkHttpClient 库 compile 'com.squareup.okhttp:okhttp:2.4.0'
			全局公用 OkHttpClient client= new OkHttpClient();
			有 Request 请求对象 和 Response 返回对象
			示例
				OkHttpClient client= new OkHttpClient();
				Request request = new Request.Builder().url("url").build();
				Response response = null;
				try {
					response = client.newCall(request).execute();
				} catch (IOException e) {
					e.printStackTrace();
					return null;
				}
				if(response.isSuccessful()){
					String c=response.body().toString();
					return c;
				}
				
		b. 使用JAVA网络库
			URL url;
			StringBuffer sb=new StringBuffer();
			try {
				url=new URL("url");
				InputStreamReader isr=new InputStreamReader(url.openStream());
				BufferedReader br= new BufferedReader(isr);
				String str;
				while((str=br.readLine())!=null)
				{
					sb.append(str);
				}
			} catch (Exception e) {
				e.printStackTrace();
				return null;
			}
			return sb.toString();
			
	3. 数据处理
		a. JSON 处理 (还有GSON等库可用)
			内置JSON:
				String json="{}";
				JSONTokener jsontoken= new JSONTokener(json);
				JSONObject jsonobject = null;
				JSONArray jsonarr;
				ArrayList<String>outarr;
				try {
					jsonobject = (JSONObject) jsontoken.nextValue();
					//JSON 简单数据类型:
					String strval=jsonobject.getString("strkey");
					//JSON 复合数据类型:
					jsonarr =jsonobject.getJSONArray("arrkey");
					outarr =new ArrayList<String>();
					for (int i=0;i<jsonarr.length();i++){
						outarr.add(jsonarr.get(i).toString());
					}
				} catch (JSONException e) {
					e.printStackTrace();
				}
				
				String json="[]";
				JSONTokener jsontoken= new JSONTokener(json);
				try {
					JSONArray jsonarr = (JSONArray) jsontoken.nextValue();
					for (int i=0;i<jsonarr.length();i++){
						JSONObject t=(JSONObject)jsonarr.get(i);
						Log.i("xxx",t.getString("tit"));
					}
				} catch (JSONException e) {
					e.printStackTrace();
				}
				
				
			GSON: 可以直接把JSON转成MODEL
				JsonParser parser = new JsonParser();
				String json1="{}";
				JsonElement objel = parser.parse(json1);
				if(!objel.isJsonObject())  return ;
				//User u = gson.fromJson(objel, User.class);
				JsonObject jobj = objel.getAsJsonObject();
				Log.i("xxx",jobj.get("tit").getAsString());

				
				String json1="{users:[]}";
				JsonParser parser = new JsonParser();
				JsonElement objel = parser.parse(json1);
				if(!objel.isJsonObject())  return ;
				JsonObject jobj = objel.getAsJsonObject();
				Gson gson = new Gson();
				List users = gson.fromJson(jobj.get("users"), new TypeToken<List>() {
				}.getType());

				String json="[]";
				JsonParser parser = new JsonParser();
				JsonElement el = parser.parse(json);
				JsonArray jsonArray = null;
				if(el.isJsonArray()){
					jsonArray = el.getAsJsonArray();
				}
				Gson gson = new Gson();
				Iterator it = jsonArray.iterator();
				while(it.hasNext()){
					JsonElement e = (JsonElement)it.next();
					User u = gson.fromJson(e, User.class);
					Log.i("xxx",u.getSrc());
				}
			
		b. XML 处理 (还有DOM SAX库可用)
			try {
				URL url;
				url=new URL("http://www.urltest.tk/a.php");
				InputStream is= null;
				is = url.openStream();
				XmlPullParser parser = Xml.newPullParser();
				int eventType = 0;
				parser.setInput(is, "UTF-8");
				eventType = parser.getEventType();
				while (eventType != XmlPullParser.END_DOCUMENT) {
					switch (eventType) {
						case XmlPullParser.START_DOCUMENT:
						   //文档开始
							break;
						case XmlPullParser.START_TAG:
							if (parser.getName().equals("book")) {
								//标签开始
							}
							break;
						case XmlPullParser.END_TAG:
							//标签结束
							break;
					}
					eventType = parser.next();
				}
			} catch (Exception e) {
				e.printStackTrace();
				return ;
			}

# dataBinding 数据绑定 启用 android {... dataBinding { enabled = true }}
	1. 视图绑定
		XML:
			<layout 
				xmlns:android="http://schemas.android.com/apk/res/android"
				xmlns:app="http://schemas.android.com/apk/res-auto"
				>
				<data class=".dataclassname">
					<import type="com.example.dome2.User" alias="Myuser" />
					<variable name="u" type="Myuser"/>
				</data>
				<TextView
					android:text='@{u.hi}'
					android:layout_width="wrap_content"
					android:layout_height="wrap_content"
					android:id="@+id/lastname"/>
			</layout>
			
		注释:
			class 属性表示视图绑定类的名 可不填,根据文件名生成
			import 引入其他类方式 alias 防止类冲突
			variable 定义变量
			
		used:
			dataclassname binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
			binding.setU(/*xxx*/);// 根据 variable 自动生成方法
			binding.lastname;//TextView 对象 根据 @+id 自动生成
			
		变量使用:
			普通对象 @{user.lastName}
			Map 对象 @{user["lastName"]}
			Liset 对象 @{user[0]}
			静态方法 @{String.valueOf(1 + (Integer)user["age"])}
			运算 	@{user.displayName ?? user.lastName}
					@{user.displayName != null ? user.displayName : user.lastName}
					@{age < 13 ? View.GONE : View.VISIBLE} //<import type="android.view.View" />
					@{@string/nameFormat(firstName)}

	2. 数据模型
		a. 自定义数据模型
			//方式一 继承 BaseObservable
				model:
				public class User extends BaseObservable {
					 private String hi;
					@Bindable //必须有注释,在BR 中生成对应KEY
					public String getHi() {
						return this.hi;
					}
					public void setHi(String hi){
						this.hi=hi;
						notifyPropertyChanged(BR.hi);//提醒修改
					}
					//定义属性的操作方式
					//定义组件属性
					//app:imageUrl="@{user.src}" 方式使用
					@BindingAdapter({"bind:imageUrl"}) 
					public static void loadImage(SimpleDraweeView view, String url) {
						Uri uri = Uri.parse(url);
						view.setImageURI(uri);
					}
					//使用自带属性
					@BindingAdapter("android:paddingLeft")
					public static void setPaddingLeft(View view, int padding) {
					   view.setPadding(padding,
						   view.getPaddingTop(),
						   view.getPaddingRight(),
						   view.getPaddingBottom());
					}
				}
				xml:
				<layout 
					xmlns:android="http://schemas.android.com/apk/res/android"
					xmlns:app="http://schemas.android.com/apk/res-auto"
					>
					<data class=".dataclassname">
						<import type="com.example.dome2.User" alias="Myuser" />
						<variable name="u" type="Myuser"/>
					</data>
					<TextView
						android:text='@{u.hi}'
						android:layout_width="wrap_content"
						android:layout_height="wrap_content"
						android:id="@+id/lastname"/>
					<com.facebook.drawee.view.SimpleDraweeView
						app:imageUrl="@{u.hi}"
						android:id="@+id/img"
						android:layout_width="100dp"
						android:layout_height="wrap_content"
						/>
				</layout>
				used:
				dataclassname binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
				User data=new User();//其他代码...
				data.setHi('xxx');
				binding.setU(data);

			//方式二 属性用 Observable 系列类
				model:
				public class User{
					public final ObservableField<String> lastName =
					   new ObservableField<>();
					public final ObservableInt age = new ObservableInt();
				}
				xml:
				<layout xmlns:android="http://schemas.android.com/apk/res/android">
					<data class=".dataclassname">
						<import type="com.example.dome2.User" alias="Myuser" />
						<variable name="userdata" type="Myuser"/>
					</data>
					<TextView
						android:text='@{userdata.lastName}'
						android:layout_width="wrap_content"
						android:layout_height="wrap_content"
						android:id="@+id/lastname"/>
				</layout>
				used:
				dataclassname binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
				User data=new User();//其他代码...
				data.firstName.set("xxx");
				binding.setUserdata(data);
				
			//方式三 无模型非列表
				xml:
				<layout xmlns:android="http://schemas.android.com/apk/res/android">
					<data class=".dataclassname">
						<import type="android.databinding.ObservableMap"/>
						<variable name="prs" type="ObservableMap<String, Object>"/>
					</data>
					<TextView
						android:text='@{prs["index"]}'
						android:layout_width="wrap_content"
						android:layout_height="wrap_content"
						android:id="@+id/lastname"/>
				</layout>
				used:
				ObservableArrayMap<String, Object> prs = new ObservableArrayMap<>();
				prs.put("index", String.valueOf(position));
				binding.setPrs(prs);
				
			//方式四 无模型简单列表
				xml:
				<layout xmlns:android="http://schemas.android.com/apk/res/android">
					<data class=".dataclassname">
						<import type="android.databinding.ObservableList"/>
						<variable name="xxx" type="ObservableList<Object>"/>
					</data>
					<TextView
						android:text='@{xxx[0]}'
						android:layout_width="wrap_content"
						android:layout_height="wrap_content"
						/>
					<TextView
						android:text='@{xxx[1]}'
						android:layout_width="wrap_content"
						android:layout_height="wrap_content"
						/>
				</layout>
				used:
				dataclassname binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
				ObservableArrayList<Object> user = new ObservableArrayList<>();
				user.add("Google");
				user.add("Inc.");
				binding.setXxx(user);
	3. 调用
		1. 未知视图绑定类
			dataclassname binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
			dataclassname binding = DataBindingUtil.inflate(LayoutInflater, layoutId, parent, attachToParent);
		2. 已知视图绑定类
			dataclassname binding = dataclassname.inflate(layoutInflater);
			dataclassname binding = dataclassname.inflate(LayoutInflater, viewGroup, false);
			dataclassname binding = dataclassname.bind(viewRoot);
			
	4. 返回视图
		dataclassname binding = dataclassname.inflate(LayoutInflater, viewGroup, false);
		binding.getRoot();

# GestureDetector VelocityTracker 触摸手势 及 触摸速度
	对屏幕的常用手势操作:
		private GestureDetector gestureDetector;
		@Override
		protected void onCreate(Bundle savedInstanceState) {
			super.onCreate(savedInstanceState);
			setContentView(R.layout.tab);
			gestureDetector = new GestureDetector(this, new GestureListener());
			gestureDetector.setIsLongpressEnabled(false);
		}
		@Override
		public boolean onTouchEvent(MotionEvent event) {
			return gestureDetector.onTouchEvent(event);
		}
		// 继承于SimpleOnGestureListener,实现所有事件监听方法
		private class GestureListener extends GestureDetector.SimpleOnGestureListener {
			@Override
			public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
				Log.i("2222", velocityX + "");
				Log.i("2222", velocityY + "");
				return super.onFling(e1, e2, velocityX, velocityY);
			}
			@Override
			public boolean onDoubleTap(MotionEvent e) {
				Log.i("test", "doubletap");
				return super.onDoubleTap(e);
			}
		}
	对屏幕的触摸速度:
		private VelocityTracker mVelocityTracker = null;
		@Override
		public boolean onTouchEvent(MotionEvent event) {
			int action = event.getAction();
			if (mVelocityTracker == null)
				mVelocityTracker = VelocityTracker.obtain();
			mVelocityTracker.addMovement(event);
			switch (action) {
				case MotionEvent.ACTION_UP:
					mVelocityTracker.computeCurrentVelocity(1000);//设置单位为毫秒
					//移动像素距离
					Log.i("11111", mVelocityTracker.getXVelocity(0) + "");
					Log.i("11111", mVelocityTracker.getYVelocity(0) + "");
					break;
			}
			return true;
		}			
			
	
# 图像资源 drawable
	1. 缩放图片
		<scale xmlns:android="http://schemas.android.com/apk/res/android"
			android:scaleWidth="50%"
			android:scaleHeight="50%"
			android:drawable="@drawable/a6"
			android:scaleGravity="center_vertical|center_horizontal"
			>
		</scale>
		
	2. 旋转图片
		<rotate xmlns:android="http://schemas.android.com/apk/res/android"
			android:drawable="@drawable/a1"
			android:visible="true"
			android:fromDegrees="-90"
			android:toDegrees="180"
			android:pivotX="50%"
			android:pivotY="50%"
			>
		</rotate>
	
	3. 叠加图片
		<?r circrsion="1.0" encoding="utf-8"?>
		<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
			<item>
				<shape android:shape="oval" >
					<solid android:color="#FFACB8C3" />
				</shape>
			</item>
			<item
				android:bottom="2dp"
				android:left="2dp"
				android:right="2dp"
				android:top="2dp">
				<shape android:shape="oval">
					<solid android:color="#FFbdcad6" />
				</shape>
			</item>
		</layer-list>
		
	4. 各种状态图片
		<?xml version="1.0" encoding="utf-8"?>
		<selector xmlns:android="http://schemas.android.com/apk/res/android">
			<!-- 默认时的背景图片-->
			<item android:drawable="@drawable/a2" android:state_focused="false" android:state_pressed="false"/>
			<!-- 按下时状态-->
			<item android:drawable="@drawable/a" android:state_pressed="true"/>
			<!--获得焦点时的图片背景-->
			<item android:drawable="@drawable/a3"  android:state_focused="true"/>
			<!--无焦点状态-->
			<item android:drawable="@drawable/a4" android:state_focused="false"/>
		</selector>
		<?xml version="1.0" encoding="utf-8" ?>
		
	5. 选择图片显示
		<?xml version="1.0" encoding="utf-8" ?>
		<level-list xmlns:android="http://schemas.android.com/apk/res/android" >
			<item
				android:drawable="@drawable/a1"
				android:maxLevel="0" />
			<item
				android:drawable="@drawable/a2"
				android:maxLevel="1" />
		</level-list>
		代码修改显示
		final ImageView imageView = (ImageView) findViewById(R.id.imgView); 
		imageView.setImageLevel(1);//默认的level为0,将到设置为1
		//或 imageView.getDrawable().setLevel(1);
		
	6. 部分显示
		<clip xmlns:android="http://schemas.android.com/apk/res/android"
			android:drawable="@drawable/a1"
			android:clipOrientation="horizontal"
			android:gravity="left" />
		代码修改显示
		ImageView imageview = (ImageView) findViewById(R.id.image);
		ClipDrawable drawable = (ClipDrawable) imageview.getDrawable();
		drawable.setLevel(drawable.getLevel() + 1000);
		
	7. 9 PNG
		将图片命名为 **.9.png 放入 drawable 之后调整边框即可
	
	8. 形状
		shape 形状 如矩形等
		<?xml version="1.0" encoding="utf-8"?>
		<shape xmlns:android="http://schemas.android.com/apk/res/android">
		<!-- 
		shape 
		android:shape=["rectangle" | "oval" | "line" | "ring"]
		矩形(rectangle)、椭圆形(oval)、线性形状(line)、环形(ring)
		-->
			<!-- 实心 -->
			<solid android:color="#ff9d77"/>
			<!-- 渐变 -->
			<gradient
				android:startColor="#ff8c00"
				android:endColor="#FFFFFF"
				android:angle="270" />
			<!-- 描边 -->
			<stroke
				android:width="2dp"
				android:color="#dcdcdc" />
			<!-- 圆角 -->
			<corners
				android:radius="2dp" />
			<padding
				android:left="10dp"
				android:top="10dp"
				android:right="10dp"
				android:bottom="10dp" />
		</shape>
		环行实例
		<?xml version="1.0" encoding="utf-8"?>
		<shape xmlns:android="http://schemas.android.com/apk/res/android"
			android:shape="ring"
			android:innerRadius="20dp"
			android:thickness="50dp"
			android:useLevel="false">
			<!--
				innerRadius 内部半径
				innerRadiusRatio 内部半径比例 innerRadius 存在 此值无效
				thickness 环厚度
				thicknessRatio 环厚度比例 thickness 存在 此值无效
			-->
			<stroke android:width="10dp"  android:color="#22ee0000" />
			<!--
			  stroke 描边
			 -->
			<solid android:color="#33ee0033"/>
			<!--
			solid  内容填
			-->
		</shape>
	9. 偏移图片
		<transition
			xmlns:android="http://schemas.android.com/apk/res/android">
			<item  android:top="-10dp" android:bottom="10dp" android:drawable="@drawable/a1" >
		    </item>
		</transition>
		
	10. 自定义图标SVG
		<?xml version="1.0" encoding="utf-8"?>
		<vector  xmlns:android="http://schemas.android.com/apk/res/android"
			android:viewportWidth="1024"
			android:viewportHeight="1024"
			android:width="1024px"
			android:height="1024px">
			<!--pathData 放置 svg path 数据-->
			<path android:fillColor="#963"  android:pathData="M511.417227 536.082488l81.180927 0 0 60.886719-81.180927 0 0-60.886719Z" />
		</vector>
		
		
# 动画 anim
	
	补间动画 anim 文件夹
		效果支持:
			Alpha:淡入淡出效果
			Scale:缩放效果
			Rotate:旋转效果
			Translate:移动效果
			
		XML 文件通过  AnimationUtils.loadAnimation(Context, R.anim.**) 获取 XML示例
			<?xml version="1.0" encoding="utf-8"?>
			<set xmlns:android="http://schemas.android.com/apk/res/android">
			<scale
				android:fromXScale="0" android:toXScale="5"
				android:fromYScale="0" android:toYScale="5"
				android:pivotX="50%" android:pivotY="50%"
				android:duration="1000" />
			</set>	
			使用
			Animation animation = (Animation) AnimationUtils.loadAnimation(Context, R.anim.**);
			
		代码里new对象 例如: AlphaAnimation alphaAnimation = new AlphaAnimation(1, 0);
		
		动画次数和方式
			animation.setRepeatCount(Animation.INFINITE);
			animation.setRepeatMode(Animation.RESTART);
			
		动画事件 setAnimationListener 示例
			animation.setAnimationListener(new Animation.AnimationListener() {
				@Override
				public void onAnimationStart(Animation animation) {
					//动画开始
				}
				@Override
				public void onAnimationEnd(Animation animation) {
					//动画结束
				}
				@Override
				public void onAnimationRepeat(Animation animation) {
					//重复动画事件
				}
			});
			
		动画效果 AccelerateInterpolator ()
			animation.setInterpolator(new AccelerateInterpolator());
			
		布局动画
			建立布局动画
				<layoutAnimation
					xmlns:android="http://schemas.android.com/apk/res/android"
					android:delay="0.5"
					android:animationOrder="normal"
					android:animation="@anim/list_anim"/>
					<!-- android:animationOrder 执行循序 normal 顺序 random 随机 reverse 反向 -->
					
			XML使用布局动画
				<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
					android:orientation="vertical"
					android:layout_width="fill_parent"
					android:layout_height="fill_parent"
					android:layoutAnimation="@anim/list_anim_layout"
				> 
				
			代码建立及使用
				Animation animation = (Animation) AnimationUtils.loadAnimation(
                  {Context}, R.anim.list_anim);
				LayoutAnimationController controller = new LayoutAnimationController(animation);
				controller.setOrder(LayoutAnimationController.ORDER_NORMAL); 
				controller.setDelay(0.5f);
				listView.setLayoutAnimation(controller);
				
		Activity 间切换 跳转之后调用 如 startActivity 之后
			overridePendingTransition(android.R.anim.slide_in_left,android.R.anim.slide_out_right);
			
		动画集
			代码: 通过 AnimationSet 包含多个动画,使用 addAnimation 添加
				 AnimationSet animationset = new AnimationSet(true);
				 animationset.addAnimation(animation);
			XML:
				<set xmlns:android="http://schemas.android.com/apk/res/android">
					<scale
						android:fromXScale="0" android:toXScale="5"
						android:fromYScale="0" android:toYScale="5"
						android:pivotX="50%" android:pivotY="50%"
						android:duration="1000" />
				</set>
			使用:
			AnimationSet animationset = (AnimationSet) AnimationUtils.loadAnimation({Context}, R.anim.**);
			
		使用动画: 调用view.startAnimation() 或 setAnimation()后在修改view内容
		
	帧动画 anim 文件夹
		建立帧
			<?xml version="1.0" encoding="utf-8"?>
			<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
				android:oneshot="false">
				<item android:drawable="@drawable/a_01" android:duration="50"/>
				<item android:drawable="@drawable/a_02" android:duration="50"/>
				<item android:drawable="@drawable/a_03" android:duration="50"/>
				<item android:drawable="@drawable/a_04" android:duration="50"/>
				<item android:drawable="@drawable/a_05" android:duration="50"/>
				<item android:drawable="@drawable/a_06" android:duration="50"/>
			</animation-list>
		
		普遍view通过 setBackgroundResource
			ImageView imageView= (ImageView)findViewById(R.id.image);
			imageView.setBackgroundResource(R.anim.anim);
			AnimationDrawable animationDrawable = (AnimationDrawable)
			 imageView.getBackground();
			animationDrawable.start();
			ImageView 还有 setImageResource
			image.setImageResource(R.anim.li);
			((AnimationDrawable)image.getDrawable()).start();
		
	差值动画 animator 文件夹
		代码建立
			TextView text = (TextView) findViewById(R.id.textView1);
			//根据属性的类型不同来调用 ofFloat ofInt ofArgb 等函数
			ObjectAnimator oa= ObjectAnimator.ofFloat(text,"TextSize",60,5);
			oa.setDuration(1000);
			oa.start();
			
		XML文件建立
			<?xml version="1.0" encoding="utf-8"?>
			<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
				android:duration="100"
				android:propertyName="TextSize"
				android:valueTo="60"
				android:valueFrom="20"
				android:valueType="floatType">
			</objectAnimator>
			调用
			ObjectAnimator obj = (ObjectAnimator) AnimatorInflater.loadAnimator({Context}, R.animator.ts);
			TextView text = (TextView) findViewById(R.id.textView1);
			obj.setTarget(text);
			obj.start();
			
		动画集
			代码: 通过 AnimationSet 包含多个动画,使用 addAnimation 添加
				 AnimationSet animationset = new AnimationSet(true);
				 animationset.addAnimation(animation);

			XML:
				<?xml version="1.0" encoding="utf-8"?>
				<set xmlns:android="http://schemas.android.com/apk/res/android">
					<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
					android:duration="100"
					android:propertyName="TextSize"
					android:valueTo="60"
					android:valueFrom="20"
					android:valueType="floatType">
					</objectAnimator>
					<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
						android:duration="100"
						android:propertyName="Height"
						android:valueTo="60"
						android:valueType="intType">
					</objectAnimator>
				</set>
				使用:
				AnimatorSet obj = (AnimatorSet) AnimatorInflater.loadAnimator({Context}, R.animator.**);
                TextView text = (TextView) findViewById(R.id.textView1);
                obj.setTarget(text);
                obj.start();

# 挂件 Widget
	1. 在 AndroidManifest 注册
		.activity.TouchActivity$myreceiver 继承自 AppWidgetProvider的类
		@xml/aa Widget 的配置文件
		<receiver android:name=".activity.TouchActivity$myreceiver" android:label="@string/app_name">
	    <intent-filter>
		     <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
		  </intent-filter>
			<meta-data
				android:name="android.appwidget.provider"
				android:resource="@xml/aa" />
	  </receiver>
	
	2. 配置文件
		@layout/aa 指定布局文件
		<?xml version="1.0" encoding="utf-8"?>
		<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
			android:minWidth="146dip" android:minHeight="72dip" android:initialLayout="@layout/aa">
		</appwidget-provider>
		
	3. 实现 AppWidgetProvider的类
		public static class myreceiver extends AppWidgetProvider {
			@Override
			public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
				//定期更新对象,如实现动画等
				Timer timer = new Timer();
				timer.scheduleAtFixedRate(new MyTime(context, appWidgetManager), 1, 1000);
				super.onUpdate(context, appWidgetManager, appWidgetIds);
			}
			public class MyTime extends TimerTask {
				RemoteViews remoteViews;
			   AppWidgetManager appWidgetManager;
				ComponentName thisWidget;
				DateFormat format = SimpleDateFormat.getTimeInstance(SimpleDateFormat.MEDIUM, Locale.getDefault());
				public MyTime(Context context, AppWidgetManager appWidgetManager) {
					this.appWidgetManager = appWidgetManager;
					//建立视图
					remoteViews = new RemoteViews(context.getPackageName(), R.layout.aa);
					//往指定包里查找视图
					thisWidget = new ComponentName(context, myreceiver.class);
				}
				@Override
				public void run() {
					//修改视图
					remoteViews.setTextViewText(R.id.text_content, "Time = " + format.format(new Date()));
					//重新设置视图
					appWidgetManager.updateAppWidget(thisWidget, remoteViews);
				}
			}
		}

# 网页 WebView
	于JS交互绑定在JS的window对象中
		final WebView vw = new WebView(this);
		vw.setWebChromeClient(new WebChromeClient() {
			@Override
			public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
				//需重写各种JS事件才能实现各种JS的方法
				AlertDialog.Builder alert = new AlertDialog.Builder(TouchActivity.this);
				alert.setTitle("Alert");
				alert.setMessage(message);
				alert.show();
				return super.onJsAlert(view, url, message, result);
			}
		});
		vw.setWebViewClient(new WebViewClient() {
			@Override
			public void onPageFinished(WebView view, String url) {
				//调用JS方法
				vw.loadUrl("javascript:hiandroid()");
			}
		});
		vw.addJavascriptInterface(new Object() {
			@JavascriptInterface
			public String alert(String string) {
				//JS调用方法
				AlertDialog.Builder alert = new AlertDialog.Builder(TouchActivity.this);
				alert.setMessage(string);
				alert.show();
				return "HI";
			}
		}, "dome");
		vw.getSettings().setJavaScriptEnabled(true);
		vw.loadUrl("http://www.urltest.tk/a.html");
		setContentView(vw);
	
# 定时器 Alarm
	设置时间已超过,将立即触发
		AlarmManager al= (AlarmManager)getSystemService(ALARM_SERVICE);
		Intent it= new Intent(MyActivity.MY_ACTION);
		PendingIntent pi=PendingIntent.getActivity(this,0,it,0);
		//AlarmManager.RTC; //指定时间,System.currentTimeMillis()+N毫秒 激活时不唤醒
		//AlarmManager.RTC_WAKEUP //指定时间,System.currentTimeMillis()+N毫秒 激活时唤醒
		//AlarmManager.ELAPSED_REALTIME;//开机时间+N毫秒 激活时不唤醒
		//AlarmManager.ELAPSED_REALTIME_WAKEUP; //开机时间+N毫秒 激活时唤醒
		al.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 10000, pi);
		//重复触发
		//al.setRepeating(AlarmManager.RTC_WAKEUP,System.currentTimeMillis()+10000,10000,pi);
		//按系统预定义重复触发 AlarmManager.INTERVAL_*
		//al.setInexactRepeating(AlarmManager.RTC_WAKEUP,System.currentTimeMillis()+10000,AlarmManager.INTERVAL_DAY,pi);

	
# 广播 Broadcast Receiver
	//常量
	public final static String MYINTERFER = "myfilterkey";
	1. 注册
		a. 代码注册
			IntentFilter intentfilter = new IntentFilter(MYINTERFER);
			BroadcastReceiver myreceiver = new BroadcastReceiver() {
				@Override
				public void onReceive(Context context, Intent intent) {
					//不要做长时间处理操作
					Toast.makeText(context,"msg",Toast.LENGTH_LONG).show();
				}
			};
			registerReceiver(myreceiver,intentfilter);
		b. AndroidManifest注册 (如果是内部类,加 static !!!应用未启动可用!!!)
			public class myreceiver extends BroadcastReceiver {
				@Override
				public void onReceive(Context context, Intent intent) {
					//不要做长时间处理操作
					Toast.makeText(context,"msg",Toast.LENGTH_LONG).show();
				}
			}
			AndroidManifest:
			<receiver android:name=".activity.TouchActivity$myreceiver">
				<intent-filter>
					<action android:name="myfilterkey" />
				</intent-filter>
			</receiver>
			
	2. 发送
		 Intent intent = new Intent(TouchActivity.MYINTERFER);
         sendBroadcast(intent);
		 
	3. 本地广播
		LocalBroadcastManager localbcm = LocalBroadcastManager.getInstance(this);
        localbcm.registerReceiver(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                //处理本地广播
            }
        },new IntentFilter(TouchActivity.MYINTERFER));
        localbcm.sendBroadcast(new Intent(TouchActivity.MYINTERFER));
		
	4. 有序广播 sendOrderedBroadcast(new Intent(TouchActivity.MYINTERFER),"权限字符串");
	
	5. 可覆盖广播,会覆盖成最后一个值 sendStickyBroadcast(new Intent(TouchActivity.MYINTERFER));
	
	6. 示例 (处理下载)
		String url = "http://dlsw.baidu.com/sw-search-sp/soft/6c/23675/Photoshop_CS6.3510481888.7z";
		Uri uri = Uri.parse(url);
		DownloadManager download = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
		DownloadManager.Request request = new DownloadManager.Request(uri);
		request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);//只在WIFI下下载
		final long enqueue = download.enqueue(request);
		//还有其他事件等等
		IntentFilter interf = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
		BroadcastReceiver br = new BroadcastReceiver() {
			@Override
			public void onReceive(Context context, Intent intent) {
				long downid = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
				if (downid == enqueue) {
					//your download
				}
			}
		};
		registerReceiver(br, interf);
	
# 服务 Service (长时间执行代码)
	1. 服务可加权限,供其他程序调用
	2. 服务可以在 Activity,Broadcast Receiver 等启动
	3. 服务的Activity交互通过 bindService 的 ServiceConnection (IBinder service) 进行
	5. 在服务中可通过回调来处理视图
	6. 服务处理过程: 创建和绑定
	7. 回调用 Handler 处理或自定义回调函数,如下示例:
		a. 服务添加
			//创建
			public static class myservice extends Service{
				private IBinder binder=new myservice.LocalBinder();
				@Override
				public IBinder onBind(Intent intent) {
					return binder;
				}
				@Override
				public void onCreate() {
					super.onCreate();
					Timer timer = new Timer();
					timer.schedule(new TimerTask() {
						@Override
						public void run() {
							if(h!=null){
								Message msg= new Message();
								Bundle b=new Bundle();
								b.putString("hehe", "Date:" + new Date().toString());
								msg.setData(b);
								h.sendMessage(msg);
							}
						}
					}, 0, 1000);
				}
				@Override
				public int onStartCommand(Intent intent, int flags, int startId) {
					//开始执行 根据返回值不同,可能会有多次调用
					return START_STICKY;
				}
				@Override
				public void onDestroy() {
					//开始结束
					super.onDestroy();
				}
				public class LocalBinder extends Binder {
					public LocalBinder() {
						super();
					}
					public myservice get_service(){
						return myservice.this;
					}
				}
				Handler h;
				public void sethandle(Handler h){
					this.h=h;
				}
			}
			//启动
			Intent intent = new Intent(this,myservice.class);
			startService(intent);
			
	b. 服务绑定 在 Activity 中
		bindService(intent, new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                myservice localser=((myservice.LocalBinder)service).get_service();
                localser.sethandle(h);
            }
            @Override
            public void onServiceDisconnected(ComponentName name) {

            }
        },BIND_AUTO_CREATE);
		
	8. Service 多次启动请求处理之类 IntentService 处理多个请求服务,任务完成会终结自己
		重写 onHandleIntent 方法即可 Intent 为请求的Intent,主要用于多个类同的服务请求
	
	
# 资源接口 Content Provider
	1. Uri 使用 
        Uri muri = Uri.parse("content://www.urltest.tk/people/111");
        UriMatcher match = new UriMatcher(UriMatcher.NO_MATCH);
        match.addURI("www.urltest.tk", "people/#", 1);
        switch (match.match(muri)) {
            case 1:
                //匹配进这里
                break;
            default:
                break;
        }
        //Uri 解析ID 和添加ID
        long id=ContentUris.parseId(muri);
        ContentUris.withAppendedId(muri,111);
		//Uri 处理路径
		Uri.withAppendedPath("content://www.urltest.tk","people"); => Uri.parse("content://www.urltest.tk/people")
		
	2. Uri 注册 provider provider实现见:3
		<provider android:name=".activity.TouchActivity$myconentp"
            android:authorities="www.urltest.tk"
            android:multiprocess="false"
            >
        </provider>
		
	3. 实现示例
		public static class myconentp extends ContentProvider{
			private static String TAG="provider";
			public static final String AUTHORITY = "www.urltest.tk";
			public static final int PEOPLES = 1;
			public static final int PEOPLE = 2;
			public static final UriMatcher match;
			static {
				match = new UriMatcher(UriMatcher.NO_MATCH);
				match.addURI(AUTHORITY, "people", PEOPLES);
				match.addURI(AUTHORITY, "people/#", PEOPLE);
			}
			public static final String CONTENT_TYPE = "vnd.android.cursor.dir/www.urltest.tk";
			public static final String CONTENT_TYPE_ITME = "vnd.android.cursor.item/www.urltest.tk";
			@Override
			public boolean onCreate() {
				Log.i(TAG,"create");
				return true;
			}
			@Nullable
			@Override
			public String getType(Uri uri) {
				switch (match.match(uri)) {
					case PEOPLES:
						return CONTENT_TYPE;
					case PEOPLE:
						return CONTENT_TYPE_ITME;
					default:
						throw new IllegalArgumentException("Unknown URI " + uri);
				}
			}
			@Nullable
			@Override
			public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
				//projection 字段列表
				//selection WHERE 条件
				//selectionArgs WHERE 绑定数据
				//sortOrder 排序
				Log.i(TAG, "query");
				switch (match.match(uri)) {
					case PEOPLE://单个查询
						long id=ContentUris.parseId(uri);//解析到ID
						break;
					case PEOPLES://批量查询
						break;
					default:
						throw new IllegalArgumentException("Unknown URI " + uri);
				}
				return null;
			}
			@Nullable
			@Override
			public Uri insert(Uri uri, ContentValues values) {
				//values 新值
				switch (match.match(uri)) {
					case PEOPLES:
						//进行添加操作
						String title=values.getAsString("title");
						Log.i(TAG, "insert:" + title);
						long insert_id=100;
						return ContentUris.withAppendedId(uri,insert_id);
					default:
						throw new IllegalArgumentException("Unknown URI " + uri);
				}
			}
			@Override
			public int delete(Uri uri, String selection, String[] selectionArgs) {
				//selection WHERE 条件
				//selectionArgs WHERE 绑定数据
				switch (match.match(uri)) {
					case PEOPLES:
						Log.i(TAG, "delete");
						//执行删除操作
						break;
					default:
						throw new IllegalArgumentException("Unknown URI " + uri);
				}
				return 1;
			}
			@Override
			public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
				//values 新值
				//selection WHERE 条件
				//selectionArgs WHERE 绑定数据
				switch (match.match(uri)) {
					case PEOPLES:
						Log.i(TAG, "update");
						//进行更新操作
						break;
					default:
						throw new IllegalArgumentException("Unknown URI " + uri);
				}
				return 0;
			}
		}
		
	4. 使用
		Uri uri = Uri.parse("content://www.urltest.tk/people");
        ContentResolver cr = getContentResolver();
        //增
        ContentValues cv = new ContentValues();
        cv.put("title", "title");
        Uri insert_uri=cr.insert(uri, cv);
        long insert_id=ContentUris.parseId(insert_uri);
        Log.i(TAG, "INSERTID:" + insert_id);
        //删
        cr.delete(uri, "id=?", new String[]{"1"});
        //改
        cv.put("title", "newtitle");
        cr.update(uri, cv, "id=" + insert_id, new String[]{String.valueOf(insert_id)});
        //查
        Cursor all_rs = cr.query(uri,null,null,null,null);
        if(all_rs!=null) {
            while (all_rs.moveToNext()) {
                String title = all_rs.getString(all_rs.getColumnIndex("title"));
            }
        }
        Uri uriitem = Uri.parse("content://www.urltest.tk/people/111");
        Cursor item_rs = cr.query(uriitem, null, null, null, null);
        if(item_rs!=null){
            String title=all_rs.getString(item_rs.getColumnIndex("title"));
        }
		
	5. 本地资源存储
		a. 数据库 SQLite 
			class myDBHelp extends SQLiteOpenHelper{
				public myDBHelp(Context context, String name, SQLiteDatabase.CursorFactory factory,
									int version) {
					super(context, name, factory, version);
				}
				public myDBHelp(Context context, String name, int version) {
					this(context, name, null, version);
				}
				@Override
				public void onCreate(SQLiteDatabase db) {
					//初始化数据库
					db.execSQL("create table mytable("
							+" id INTEGER PRIMARY KEY autoincrement,"
							+ " title varchar(20)"
							+");");
				}
				@Override
				public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
					//升级数据库
				}
			}
			使用
			myDBHelp dbhelp= new myDBHelp(this,"db_name",5);
			SQLiteDatabase db = dbhelp.getWritableDatabase();
			//增
			ContentValues insval = new ContentValues();
			insval.put("title", "title");
			long id = db.insert("mytable", null, insval);
			//改
			insval.put("title", "newtitle");
			db.update("mytable",insval , "id=?",new String[]{String.valueOf(id)} );
			//查
			Cursor db_rs = db.query("mytable", new String[]{"title"},null, null, null, null, null);
			if(db_rs!=null) {
				while (db_rs.moveToNext()) {
					String title = db_rs.getString(db_rs.getColumnIndex("title"));
					Log.i(TAG,title);
				}
			}
			//删
			db.delete("mytable", "id=?", new String[]{String.valueOf(id)});
			
		b. 键值对 SharedPreferences 示例
			SharedPreferences mySharedPreferences= getSharedPreferences("test", Activity.MODE_PRIVATE);
			SharedPreferences.Editor editor = mySharedPreferences.edit();
			editor.putString("name", "Karl");
			editor.commit();
			String name=mySharedPreferences.getString("name","unkown");
			Log.i("myout",name);	
			
		c. 文件 
			try {
				String msg="hi";
				String file="message.txt";
				FileOutputStream fos = openFileOutput(file,
						MODE_APPEND);
				fos.write(msg.getBytes());
				fos.close();

				FileInputStream inStream = this.openFileInput(file);
				byte[] buffer = new byte[1024];
				int hasRead = 0;
				StringBuilder sb = new StringBuilder();
				while ((hasRead = inStream.read(buffer)) != -1) {
					sb.append(new String(buffer, 0, hasRead));
				}
				inStream.close();
				Log.i("myout",sb.toString());
			} catch (Exception e) {
				e.printStackTrace();
			}
			
		d. SD卡文件
			缓存文件夹 getCacheDir(); getExternalCacheDir()
			if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
				String filename="filename.txt";
				String msg="this is txt";
				File file = new File(Environment.getExternalStorageDirectory()
						.toString()
						+ File.separator
						+ filename);
				if (!file.getParentFile().exists()) { // 父文件夹不存在
					file.getParentFile().mkdirs(); // 创建文件夹
				}
				PrintStream out = null; // 打印流对象用于输出
				try {
					out = new PrintStream(new FileOutputStream(file, true)); // 追加文件
					out.println(msg);
				} catch (Exception e) {
					e.printStackTrace();
				} finally {
					if (out != null) {
						out.close(); // 关闭打印流
					}
				}
				Scanner scan = null; // 扫描输入
				StringBuilder sb = new StringBuilder();
				try {
					scan = new Scanner(new FileInputStream(file)); // 实例化Scanner
					while (scan.hasNext()) { // 循环读取
						sb.append(scan.next()); // 设置文本
					}
					Log.i("myout",sb.toString());
				} catch (Exception e) {
					e.printStackTrace();
				} finally {
					if (scan != null) {
						scan.close(); // 关闭打印流
					}
				}
			} else {
				// SDCard不存在,使用Toast提示用户
			}

			

# 提醒 Notification
	//常量
	public final static int TAG = 1;
	1. API 11 后示例
		PendingIntent pendingIntent2 = PendingIntent.getActivity(this, 0,
				new Intent(this, TouchActivity.class), 0);
		Notification notify2 = new Notification.Builder(this)
				.setSmallIcon(R.drawable.abc_btn_check_to_on_mtrl_015) 
				.setTicker("TickerText:" + "您有新短消息,请注意查收!")
				.setContentTitle("Notification Title")
				.setContentText("This is the notification message")
				.setContentIntent(pendingIntent2)
				.setNumber(1)
				.getNotification(); // 需要注意build()是在API level
		// 16及之后增加的,在API11中可以使用getNotificatin()来代替
		notify2.flags |= Notification.FLAG_AUTO_CANCEL;
		manager.notify(TAG, notify2);
		
	2. API 16 后示例
		PendingIntent pendingIntent3 = PendingIntent.getActivity(this, 0,
				new Intent(this, TouchActivity.class), 0);
		Notification notify3 = new Notification.Builder(this)
				.setSmallIcon(R.drawable.notification_template_icon_bg)
				.setTicker("TickerText:" + "您有新短消息,请注意查收!")
				.setContentTitle("Notification Title")
				.setContentText("This is the notification message")
				.setContentIntent(pendingIntent3).setNumber(1).build(); 
		notify3.flags |= Notification.FLAG_AUTO_CANCEL; // FLAG_AUTO_CANCEL表明当通知被用户点击时,通知将被清除。
		manager.notify(TAG, notify3);
		
	3. 自定义提醒视图 (Deprecated)
		Notification myNotify = new Notification();
		myNotify.icon = R.drawable.notification_template_icon_bg;
		myNotify.tickerText = "TickerText:您有新短消息,请注意查收!";
		myNotify.when = System.currentTimeMillis();
		myNotify.flags = Notification.FLAG_NO_CLEAR;// 不能够自动清除
		RemoteViews rv = new RemoteViews(getPackageName(),
				R.layout.aa);
		rv.setTextViewText(R.id.text_content, "hello wrold!");
		myNotify.contentView = rv;
		Intent intent = new Intent(Intent.ACTION_MAIN);
		PendingIntent contentIntent = PendingIntent.getActivity(this, 1,
				intent, 1);
		myNotify.contentIntent = contentIntent;
		manager.notify(TAG, myNotify);
		
	4. 关闭提醒
		manager.cancel(TAG);

  

原文地址:https://www.cnblogs.com/liushannet/p/3113196.html