精华内容
下载资源
问答
  • Android 四大组件,五大存储,六大布局

    万次阅读 多人点赞 2018-08-15 12:28:24
    Android 四大组件 android四大组件分别是:Activity, service,content provider,broadcast receiver ...Android 五大存储 SharedPreferences 方式 文件存储方式 SQList 存储...

    Android 四大组件

    android四大组件分别是:Activity, service,content provider,broadcast receiver

    一、Activity

    1、概念:

    android 中,Activity 相当于一个页面,可以在Activity中添加Button、CheckBox 等控件,一个android 程序有多个Activity组成。

    2、生命周期:

    这里写图片描述

    3、四中启动模式

    Standard 模式 : standard 模式是android 的默认启动模式,在这种模式下,activity可以有多个实例,每次启动Activity,无论任务栈中是否已经存在这个activity的实例,系统都会创建一个新的activity实例。

    SingleTop 模式: 栈顶模式,当一个singleTop模式的activity 已经位于栈顶时,再去启动它时,不在创建实例,如果不在栈顶,就会创建实例。

    SingleTask 模式 : 单任务模式,如果启动的activity 已经存在于 任务栈中,则会将activity移动到栈顶,并将上面的activity出栈,否则创建新的实例

    SingleInstance 模式 :单实例模式,一个activity 一个栈。

    4、三种跳转方式

    显示启动
    Intrent 内部直接声明要启动的activity所对应的的class

    Intent intent = new Intent(MainActivity.this, SecondActivity.class);
    startActivity(intnet);
    

    隐式启动
    进行三个匹配,一个是activity,一个是category,一个是data,全部或者部分匹配,应用于广播原理

    • 清单文件中 里配置activity属性,activity的名字要和跳转内容一样
    <activity 
    	android:name="com.exanple.android.tst.secondActivity"
    	android:label = @string/title>
    	<intent=filter>
    		<action android:name="com.exanple.android.tst.secondActivity/>
    		<category android:name="android.intent.category.DEFAULT"/>
    	<intent-filter/>
    </activity>
    
    • 在需要跳转的地方
    Intent intent = new Intent("com.example.android.tst.secondActivity");
    startActivity(intnet);
    

    跳转后再返回,能获取返回值

    Intent in = new Intent(MainActivity.this,OtehrActivity.class);
    in.putExtra("a",a);
    startActivityForResult(in,1000);
    

    在OTherActivity中设置返回值

    Intent int = new Intent();
    int.putExtra("c",c);
    setResult(1001,int);
    finish();
    

    在MainActivity中获取返回值

    @Override
    protected void onActivityResult(int requestCode, int resultCode	,Intent data) {
    	super.onActivityResult(requestCode,resultCode,data);
    	if(requestCode == 1000){
    		if(resultCode == 1001){
    			int c = data.getExtra("c",0);
    		}
    	}
    }
    

    Service

    定义一个Server

    项目内Server包 右键 --> New --> Service --> Service 或者直接创建Class类,继承Service并重写IBinder方法

    public class MyService extends Service{
    	
    	public MyService(){
    		
    	}
    
    	@Override
    	public IBinder onBind(Intent intent) {
    		return null;
    	}
    	
    	@Override
    	public void onCreate() {
    		super.onCreate();
    	}
    	
    	@Override
    	public int onStartCommand(Intent intent, int flags, int startId) {
    		return super.onStartCommand(intent, flags, startId);
    	}
    	
    	@Override
    	public void onDestroy() {
    		// TODO Auto-generated method stub
    		super.onDestroy();
    	}
    }
    

    重写Service的 onCreate()、onStartCommand()和onDestory()方法。其中 onCreate() 方法在服务创建的时候调用、onStartCommand() 方法会在每次服务启动的时候调用、onDestory() 方法会在服务销毁的时候调用。
    通常情况下,如果我们希望服务一旦启动就立刻去执行任务,就可以将逻辑卸载onStartCommand() 方法里。
    另外需要注意的是,每个服务都需要在Androidmanifest.xml 中进行注册才能生效:

    <application
    	....>
    	...
    	<service
    		android:name=".MyService"
    		android:enabled="true"
    		android:exported="true">
    	</service>
    </application>
    
    启动和停止服务

    启动服务:

    Intent startIntent = new Intent(this, MyService.class);
    startService(startIntent); //启动服务
    

    停止服务:

    Intent stopIntent = new Intent(this, MyService.class);
    stopService(stopIntent); //停止服务
    
    使用前台服务

    前台服务与普通服务的最大区别在于,它会一直有一个正在运行的图标在系统的状态栏中,下拉状态栏后可以看到更加详细的内容,非常类似于通知的效果。

    public class MyService extends Service{
    	Intent intent = new Intent(this, MainActivity.class);
    	PendingIntent pi = PendingIntent.getActivity(this, 0 , intent, 0);
    	Notification notification  = new NotificationCompat.Builder(this)
    		.setContentTitle(" this is content titile")
    		.setContentText("this is content text")
    		.setWhen(System.currentTimeMillis())
    		.setSmallIcon(R.mipmap.ic_launcher);
    		.setLargeIcon(BitmapFactory.decodeResource(getResource(),
    			R.mipmap.ic_launcher))
    		.setContentIntent(pi)
    		.build();
    	startForeground(1,notification);
    }
    

    构造一个Notification对象后并没有使用NotificationManager 来讲通知显示出来,而是调用了startForeground()方法,该方法会将MyService变成一个前台服务,并在系统状态栏中显示出来。

    使用IntentService

    服务中的代码都默认运行在主线程中,如果直接在服务中执行耗时操作很容易出现ANR(Application not Responding)
    所以这个时候需要用到Android多线程编程技术,我们应该在服务的每个具体的方法里启动一个子线程,然后在这里去处理那些耗时的操作:

    public class MyService extends Service{
    	...
    	@Override
    	public int onStartCommand(Intent intent , int flags, int startId){
    		new Thread(new Runnable(){
    			public void run(){
    				//处理具体的逻辑
    			}
    		}).start();
    		return super.onStartCommand(intent, flags, startId);
    	}
    }
    

    但是,这种服务一旦启动之后,就会一直处于运行状态,必须调用stopService()或者stopSelf()方法才能让服务停止下来,所以,如果想要实现让一个服务在执行完毕后自动停止的功能,就可以这样写:

    public class MySerivce extends Servcie{
    	...
    	@Override
    	public int onStartCommand(Intent intent, int flats , int startId){
    		new Thread(new Runnable(){
    			public void run(){
    				//处理具体的逻辑
    				stopSelf();
    			}
    		});
    	}
    }
    

    虽说这样的写法并不复杂,但是总会有一些程序员忘记开启线程或者忘记调用stopSelf() 方法。为了简单创建一个异步、会自动停止的服务。Android专门提供了一个IntentService类

    public class MyIntentService extends IntentService{
    	public MyIntentService(){
    		super("MyIntentService");  //调用父类的有参构造方法
    	}
    	@Override
    	protected void onHandleIntent(Intent intent){	
    		//打印当前的线程ID
    		Log.e("mylog","Thread id is” + Thread.cuttentThread().getId();
    	}
    	@Override
    	public void onDestory(){
    		super.onDestory();
    		Log.e("mylog","on Destory executed");
    	}
    }
    

    首先这里提供一个无参的构造方法,并且必须在其内部调用父类的有参构造方法。然后要在子类中去实现onHandleIntent() 这个抽象方法,在这个方法中可以去处理一些逻辑,而且不用担心ANR,因为这个方法已经是在子线程中运行了。
    IntentService线程的调用:

    Intent intent = new Intent(this, MyIntentService.class);
    startServcie(intent);
    

    如此,线程就会自动启动并执行逻辑,执行完毕后自动关闭。这就是IntentService 的好处,能够自动开启和关闭;

    Content Provider

    对于每一个应用程序来说,如果想要访问内容提供器中共享的数据,就一定要借助ContentResolver 类,可以通过Context中的getContentResolver() 方法获取该类的实例。ContentResolver中提供了一系列的方法用于对数据进行CRUD操作,其中insert() 方法用于添加数据,update() 方法用于更新数据,delete() 方法用于删除数据,query() 方法用于查询数据。
    不同于SQLiteDatabase,ContentResolver 中的增删改查都是接收一个URl参数,这个参数被称为内容URL。内容URL给内容提供器中的数据建立了唯一标识符,它主要由两部分组成:authoritypathauthority 是用于对不同的应用程序做区分的,一般为了避免冲突,都会采用程序包名的方式进行命名。path则是用于对同一应用程序中不同的表做区分,通常都会添加到authority后面:

    content://com.example.app.provider/table1
    content://com.example.app.provider/table2
    

    在使用内容URL作为参数的时候,需要将URL转换成URL对象:

    Uri uri = Uri.parse("content://com.example.app.provider/table1")
    

    现在我们就可以使用这个uri对象来查询talbe1表中的数据了:

    Cursor cursor = getContentResolver().query(
    	uri,
    	projection,
    	selection,
    	selectionArgs,
    	sortOrder
    );
    

    对应参数的解释:

    query()方法参数 对应SQL部分 描述
    uri from table_name 指定查询某个应用程序下的某个表
    projection select column1, column2 指定查询的列名
    selection where column=value 指定where约束条件
    selectArgs - 为where中的占位符提供具体的值
    orderBy order by column1, column2 指定查询结果的排序方式

    查询完之后,就可以从游标中取值了:

    if(cursor != null){
    	while(cursor.moveToNext()) {
    		String column1 = cursor.getString(cursor.getColumnIndex("column1"));
    		int column2 = cursor.getInt(cursor.getColumnIndex("column2"));
    	}
    	cursor.close();
    }
    
    增删改查

    添加数据

    ContentValues values = new ContentValues();
    values.put(“column1”, "text");
    values.put("column2", 1);
    getContentResolver().insert(uri, values);
    

    更新数据

    ContentValues valuse = new ContentValues();
    valuse.put("column1", "");
    getContentResolver().update(uri, values, "column1 = ? and column2 = ?", new String[]{"text", 1});
    

    删除数据

    getContentResolver().delete(uri , "column2 = ?", new String[]{ "1"});
    
    实例.

    读取系统联系人
    读取系统联系人需要声明权限,如果系统是6.0以后的,需要申请运行时权限

    if(ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) 
    	!= PackageManager.PERMISSION_GRANTED) {
    		ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CONTACTS}, 1);
    	}else {
    		readContacts();  //读取联系人
    	}
    private void readContacts(){
    	Cursor cursor = null;
    	try{
    		//查询联系人数据
    		cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,null,null,null);
    		if(cursor!=null){
    			while(cursor.moveToNext()){
    				//获取联系人姓名
    				String name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
    				//获取联系人电话号码
    				String number = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
    				list.add(name+"\n"+number);
    			}
    		}
    	}catch(Exception e){
    		e.printStackTrace()
    	}finally{
    		if(cursor != null){
    			cursor.close();
    		}
    	}
    }
    
    @Override
    public void onRequestPermissionResult(int requestCode, String[] permissions, int[] grantResults){
    	switch(requestCode){
    		case 1:
    			if(grantResults.length >0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
    				readContacts();
    			}else {
    				//您拒绝了权限
    			}
    	}
    }
    
    创建自己的内容提供器

    创建自己的内容提供器,需要去继承 ContentProvider 类,ContentProvider 类中有6个抽象方法,我们在使用子类继承它的时候,需要将这6个方法全部重写。

    public class MyProvider extends ContentProvider{
    	@Override
    	public boolean onCreate() {
    		return false;
    	}
    	@Override
    	public Cursor query(Uri uri, String[] projection, Stirng selection, String[] selectionArgs, String sortOrder){
    		return null;
    	}
    	@Overrride
    	public Uri insert(Uri uri , ContentValues values){
    		return null;
    	}
    	@Override
    	public int update(Uri uri, ContentValuse values, String selection, String[] selectionArgs){
    		return 0;
    	}
    	@Override
    	public int delete(Uri uri, String selection, String[] selectionArgs){
    		return 0;
    	}
    	@Override
    	public String getType(Uri uri){
    		return null;
    	}
    }
    

    URI 的主要格式有以下两种

    content://com.example.app.provider/table1
    content://com.example.app.provider/table1/1
    
    * : 表示匹配任意长度的任意字符
    # : 表示匹配任意长度的数字
    
    //一个能够匹配任意表的内容URI格式就可以写成:
    content://com.example.app.provider/*
    //一个能够匹配表中任意一行数据的内容URI格式就可以写成:
    content://com.example.app.provider/table1/#
    

    Broadcast Receiver

    android 广播分为两个角色:广播发送者、广播接收者
    android 广播:
    1),用于不同组件间的通信(含:应用内/不同应用之间)
    2),用于多线程通信
    3),与android系统的通信

    自定义广播接收者
    • 继承BroadcastReceive 基类
    • 必须重写抽象方法onReceive()方法
    1,广播接收器收到相应广播后,会自动调用onReceive() 方法
    2,一般情况下,onReceive方法会会涉及与其他组件之间的交互,如 发送Notiotification,启动server等
    3,默认情况下,广播接收器运行在UI线程,因此,onReceive方法不能执行耗时操作,否则将导致ANR
    
    广播接收器注册

    注册的方式有两种:静态注册、动态注册
    静态注册

    • 注册方式:在AndroidManifest.xml 里通过<receive 标签声明
    • 属性说明
    <receiver
    	android:enable="true"/"false"
    	//此broadcastReceiver 是否接受其他应用发出的广播
    	//默认值时由receiver 中d有无inter-filter决定,如果有,默认true,否则默认false
    	android:exported="true"/"false"
    	android:icon="drawable resource"
    	android:label="string resource"
    	//继承BroadcastReceiver子类的类名
        android:name=".mBroadcastReceiver"
    //具有相应权限的广播发送者发送的广播才能被此BroadcastReceiver所接收;
        android:permission="string"
    //BroadcastReceiver运行所处的进程
    //默认为app的进程,可以指定独立的进程
    //注:Android四大基本组件都可以通过此属性指定自己的独立进程
        android:process="string" >
    
    //用于指定此广播接收器将接收的广播类型
    //本示例中给出的是用于接收网络状态改变时发出的广播
     <intent-filter>
    	<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
     </intent-filter>
     </receiver>
    

    注册示例:

    <receiver 
        //此广播接收者类是mBroadcastReceiver
        android:name=".mBroadcastReceiver" >
        //用于接收网络状态改变时发出的广播
        <intent-filter>
            <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
        </intent-filter>
    </receiver>
    

    当此APP首次启动时,系统会自动实例化mBroadcastReceiver类,并注册到系统中。

    动态注册

    • 注册方式:在代码中调用Context.registerReceiver() 方法
    • 具体代码如下:
    	// 1. 实例化BroadcastReceiver子类 &  IntentFilter
         mBroadcastReceiver mBroadcastReceiver = new mBroadcastReceiver();
         IntentFilter intentFilter = new IntentFilter();
    
        // 2. 设置接收广播的类型
        intentFilter.addAction(android.net.conn.CONNECTIVITY_CHANGE);
    
        // 3. 动态注册:调用Context的registerReceiver()方法
         registerReceiver(mBroadcastReceiver, intentFilter);
    
    
    //动态注册广播后,需要在相应位置记得销毁广播
    unregisterReceiver(mBroadcastReceiver);
    

    特别注意
    动态广播最好在onResume中注册, onPause注销
    原因:
    1,对于动态广播,有注册必然得有注销,否则会导致内存泄漏
    2,onPause在App死亡前一定会被执行,从而保证app死亡前一定会被注销,从而防止内存泄漏

    两种注册方式的区别

    在这里插入图片描述

    广播的发送

    广播的发送 = 广播发送者 将此广播的意图(intent)通过 sendBroasdcast() 方法发送出去
    广播的类型

    • 普通广播 系统广播 有序广播 粘性广播 App 应用内广播
    特别注意:

    对于不同注册方式的广播接收器回调OnReceive(Context context,Intent intent)中的context返回值是不一样的:

    • 对于静态注册(全局+应用内广播),回调onReceive(context,
      intent)中的context返回值是:ReceiverRestrictedContext;
    • 对于全局广播的动态注册,回调onReceive(context, intent)中的context返回值是:Activity
      Context;
    • 对于应用内广播的动态注册(LocalBroadcastManager方式),回调onReceive(context,
      intent)中的context返回值是:Application Context。
    • 对于应用内广播的动态注册(非LocalBroadcastManager方式),回调onReceive(context,
      intent)中的context返回值是:Activity Context;

    Android 五大存储

    SharedPreferences 方式

    SharedPreferences 是使用键值对的方式进行存储数据的。
    想要使用SharedPreferences 来存储数据,首先主要获取到SharedPreferences 对象。Android提供了三种方法用于获取SharedPreferences对象:
    1,Context类中的getSharedPreferences()方法

    //此方法接收两个参数,一个参数用于指定SharedPreferences文件的名称,如果指定的文件不存在则会创建一个,SharedPreferences文件都是存放在/data/data/<package name>/shared_prefs/目录下
    //第二个参数用于指定操作模式,目前只有MODE_PRIVATE这种模式,和直接传入0效果相同
    SharedPreferences.Editor editor = getSharedPreferences("data",MODE_PRIVATE).edit();
    editor.putString("name", "Tom");
    editor.putInt("age",13);
    editor.putBoolean("married",false);
    editor.apply();
    

    2,Activity类中的getPreferences()方法

    //这个方法和Context中的getSharedPreferences()方法很类似,不过它只接收一个操作模式,因为使用这个方法时会自动将当前活动的类名作为SharedPreferences的文件名
    

    3,PreferencesManager类中的getDefaultSharedPreferences()方法

    //这是一个静态方法,它接收一个Context参数,并自动使用当前应用程序的包名作为前缀来命名SharedPreferences文件
    

    得到了SharedPreferences对象后, 就可以开始想SharedPreferences文件中存储数据了,主要可以分为三步:
    (1)调用SharedPreferences对象的edit()方法来获取一个SharedPreferences.Editor对象
    (2)向SharedPreferences.Editor 对象中添加数据,比如添加一个布尔值,可以使用putBoolean() 方法
    (3)调用apply()方法的添加的数据提交,从而完成数据存储操作

    SharedPreferences中读取数据
    SharedPreferences pref = getSharedPreferences("data",MODE_PRIVATE	);
    String name = pref.getString("name","");
    int age = pref.getInt("age",0);
    boolean married = pref.getBoolean("married", false);
    

    文件存储方式

    SQList 存储方式

    Android 为了让我们能够更加方便的管理数据库,专门提供了一个SQLiteOpenHelper 帮助类,借助这个类可以非常简单的将数据库进行创建好升级。
    SQLiteOpenHelper 中有两个非常重要的实例方法,getReadableDatabase()getWritableDatabase() 。这两个方法可以创建或者打开一个现有的数据库(如果数据库存在则直接打开,否则创建一个新的数据库),并返回一个可对数据库进行读写操作的对象。不同的是,当数据库不可写入(如磁盘空间已满),getReadableDatabase方法返回的对象将以只读的方式打开数据库,而getWeitableDatabase则出现异常

    例子(在指定路径下创建数据库文件 .db )

    public class MainActivity extends Activity {
    	public static final String PATH_ONE = "KogBill";
    	public static final String PATH_NAME = "KogBill.db";
    	private SQLiteDatabase db;    //声明SQLiteDatabase ,该对象可以操作数据库
    
    	String path = Environment.getExternalStorageDirectory().getAbsolutePath();
    	String path1 = path + File.separator + PATH_ONE;   //需要创建的路径
    	String path2 = path + File.separator + PATH_ONE + 
    			File.separator + PATH_NAME;  							//需要创建的文件
    
    	@Override
    	protected void onCreate(Bundle savedInstanceState){
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    		File f = new File(path1);
    		if( !f.exists()){  //创建数据库文件路径
    			f.mkdirs();
    		}	
    		//实例化MySQLiteHelper ,创建指定目录下数据库文件,并创建表
    		MySQLiteHelper mSQL = new MySQLiteHelper(MainActivity.this, path2);
    		db = mSQL.getWritableDatabase();
    	}
    
    	class MySQLiteHelper extends SQLiteOpenHelper{
    			private static final int DATABASE_VERSION = 1;//数据库版本号
    			private static final String CREATE_TABLE = "create table kog_bill ("
    		            + "_id integer primary key autoincrement,"
    		            + "date text, "
    		            + "breakfast text, "
    		            + "lunch text,"
    		            + "dinner text,"
    		            + "happy text,"
    		            + "other text,"
    		            + "spare text)";
    			
    			//方便创建实例,简化构造方法,方法内调用4参数构造方法
    			//参数 name 可以是 数据库名称,也可以数据库文件路径(即可以指定数据库文件路径)
    			public MySQLiteHelper(Context context, String name) {
    				this(context, name, null, DATABASE_VERSION);
    			}
    			//必须要实现的方法
    			public MySQLiteHelper(Context context, String name, CursorFactory factory, int version) {
    				super(context, name, factory, version);
    			}
    	
    			@Override
    			public void onCreate(SQLiteDatabase db) {
    				// 第一次创建数据库时 才会调用
    				Log.e("mylog", "创建数据库表");
    				db.execSQL(CREATE_TABLE);
    			}
    	
    			@Override
    			public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    			}
    			
    		}
    }
    

    根据上述代码,便获得db对象,通过db(SQLiteDatabase)可进行数据库的操作,如 db.query() db.delete()

    如果我们想在创建一个数据库表,参照上述代码,可以在SQLiteOpenHelper的onCreate方法中加入语句:

    @Override
    public void onCreate(SQLiteDatebase db) {
    	db.execSQL(CREATE_TABLE);
    	db.execSQL(CREATE_BOOK);  //新创建一个数据库表
    }
    

    然后重新运行一下,发现并没有创建成功,因为KogBill.db数据库已经存在,所以MySQLiteHelper 中的onCreate方法都不会执行,解决这个办法的方法很简单,只需要将db文件删除,重新运行,便可成功,但是原来数据库中的数据都会被删除。所以需要用到MySQLiteHelper中的update方法。

    class MySQLiteHelper extends SQLiteOpenHelper{
    	.....
    	@Override
    	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){
    		db.execSQL("drop table if exists book");  //如果已经存在就删除,防止重复创建
    		onCreate(db);  // 再次执行onCreate 方法
    	}
    }
    

    但是onUpgrade方法默认是不执行的,如何让onUpgrade方法执行,需要用到MySQLiteHelper 构造参数中的版本号:

    private static final int DATABASE_VERSION = 1;//  将版本号 由 1 改为2 
    

    这里将数据库版本号由1改为2,表示对数据库的升级

    数据库的增删改查

    添加数据

    ContentValues values = new ContentValues();
    	values.put("date", str1.isEmpty()?"0.0":str1);
    	values.put("breakfast", ""+str2);
    	values.put("lunch", ""+str3);
    	values.put("dinner", ""+str4);
    	values.put("happy", ""+str5);
    	values.put("other", ""+str6);
    	values.put("spare", ""+str7);
    	long ii = db.insert("kog_bill", "", values);
    	values.clear();
    	if(ii != -1) {
    		Utils.showToast("保存成功!", MainActivity.this);
    	}else {
    		Utils.showToast("保存失败!", MainActivity.this);
    	}
    

    更新数据

    ContentValues valus = new ContentValues();
    valuse.put("other","12");
    db.update("kogBill", values, "_id=?",new String[]{id});
    

    删除数据

    db.delete("kogBill", "_id=?",new String[]{id});
    

    查询数据

    db.query("kog_bill", new String[]{"_id","date","breakfast","lunch","dinner","happy","other","spare"}
    		, null, null, null, null, "date desc");
    
    使用SQL操作数据库

    虽然Android 已经给我们提供了非常方便的API用于操作数据库,不过总会有些人不习惯去使用这些辅助行的方法,而是更加青睐于直接使用SQL来操作数据库,当然Android也是提供的。
    添加数据

    db.execSQL("insert into kogBill ("date","breakfest","lunch","dinner","happy","other","spare") values (?,?,?,?,?,?,?)", new String[]{"1921-1-1",“123”,“1”,“1”,“11”,“2”,“3”});
    

    更新数据

    db.execSQL("update kogBill set other = ? where _id = ? ", new String[]{"12",id});
    

    删除数据

    db.execSQL("delete from kogBill where _id = ?”, new String[]{id});
    
    使用 LitePal 操作数据库

    假设编译环境为AndroidStudio。
    1,引进包

    dependencies{
    	compile fileTree(dir:'libs', include:['*.jar'])
    	compile 'com.android.support:appcompat-v7:23.2.0'
    	testCompile 'junt:junt:4.12'
    	compile 'org.litepal.android:core:1.3.2'   //引入litepal包
    }
    

    2,配置litepal.xml 文件
    右键app/src/main 目录->New -> Directory ,创建一个assets目录,然后在 assets目录下再新建一个litepal.xml 文件,接着编辑文件中的内容

    <?xml version='1.0' encoding="utf-8"?>
    <litepal>
    	<dbname value = "BookStore"></dbname>
    	<version value="1"></version>
    	<list></list>
    </listepal>
    

    其中,<dbname 标签用来指定数据库名,<version 用来指定数据库版本号,<list 标签用来指定所有映射模型。
    最后还需要在配置以下 LitePalApplication, 修改AndroidManifest.xml 中的代码

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    	package="com.example.litepaltest" >
    	<application
    		android:name="org.litepal.LitePalApplication"  //配置 LitePalApplication
    		android:allowBackup="true"
    		.....
    	</application>
    </manifest>
    

    以上,LitePal的配置工作已经结束了,接下来使用LitePal。
    首先将需要实现 javabean类 对应 数据库表.
    然后将javabean类添加到映射模型列表中,修改litepal.xml 中的代码

    <litepal>
    	<dbname value="kogBill" ></dbname>
    	<version value="1"></version>
    	<list>
    		<mapping class="com.example.litepaltest.book"></mapping>  //javabean类的路径
    	</list>
    

    这样所有工作就已经完成,现在只要进行任意一次数据库的操作,数据库db文件就会自动创建,比如:

    Connector.getDatabase();
    
    操作数据

    如果需要对某个表进行数据操作,需要让其对应的javaBean类继承DataSupport

    public class Book extends DataSupport { //让对应的类继承DataSupport
    	...
    }
    

    接下来,进行添加数据的操作:

    Book book = new Book();
    book.setName("...");
    book.setAuthor("...");
    book.setPages(234);
    book.setPrice(12,21);
    book.setPress("unkow");
    book.save();  //执行sava 就可以插入数据了
    

    执行更新数据:

    Book book = new Book();
    book.setPrice(11.11);
    book.setPress("Anchor");
    book.updateAll("name = ?  and authro = ?","..","...");
    

    删除数据:

    DataSupport.deleteAll(Book.class, "price<?","13");
    

    查询数据:

    //查询所有
    List<Book> books = DataSupport.findAll(Book.class);  
    // 查询第一条
    List<Book> books = DataSupport.findFirst(Book.class);
    //查询最后一条
    List<Book> books = DataSupport.findLast(Book.class);
    //查询那几列的数据
    List<Book> books = DataSupport.select("name","author).find(Book.class);
    //条件查询, 页面大于400
    List<Book> books = DataSupport.where("pages >?","400").find(Book.class);
    //将 price 降序排序
    List<Book> books = DataSupport.order(price desc").find(Book.class);
    //查询前3条
    List<Book> books = DataSupport.limit(3).find(Book.class);
    //从下表1开始,往后查询3条
    List<Book> boods = DataSupport.limit(3).offset(1),find(Book.class)
    

    当然这些方法也可以组合起来使用:

    
    List<Book> books = DataSupport.select("name","author","pages")
    															.where("pages>?”,"400")
    															.order("pages")
    															.limit(10)
    															.offset(10)
    															.find(Book.class);
    

    如果有些特殊查询,使用上述方法无法查询时,可以使用如下语句:

    Cursor c  = DataSupport.findBySQL("select * from Book where pages > ? and price < ?”, 
    		"400","20”);
    

    内容提供器(Conent Provider)方式

    网络存储方式

    Android 六大布局

    LinearLayout 线性布局

    线性布局,如名字所描述的那样,这个布局将它所包含的控件在线性方向上一次排列,方向分为 水平方向和数值方向。
    属性 android:orientation = “vertical” | “horizontal” 竖直或水平,默认水平
    属性 android:layout_gravity = “top” | “center” | “bottom” 内部的布局方式
    属性 android:gravity = “top”|"center”|“bottom” 相对于父容器的对齐方式
    属性 android:layout_weidht 使用比例方式执行控件的大小,在手机屏幕适配方面起到非常重要的作用

    TableLayout 表格布局

    表格布局与HTML中的table td tr标签类似

    <table>
    	<tr><td></td></tr>
    </table>
    
    

    如何确定行与列

    • 如果在TableLayout下添加组件,这个组件会占满整行
    • 如果想把多个组件放在同一行,需要添加TableRow的容器,然后把组件放进去
    • TableRow中的组件个数决定的该行的列数,而列的宽度由列中最宽的单元格决定
    • TableRow嗯layout_width属性默认是fill-parent,修改无效。但是layout_height默认是wrapcontent,可以修改
    • 整个表格的宽度取决于父容器的宽度(占满父容器)

    重要的属性:

    • android:collapaseColumns:设置需要被隐藏的列的序号
    • android:shrinkColumns:设置允许被收缩的列的序号
    • android:stretchCoumns:设置运行被拉伸嗯列的序号
      这三个属性都是从0开始算的
    shrinkColumns= "2" //对应第三行
    shrinkColumns = '"0,2" //设置多个都生效
    shrinkColumns = "" //所有列都生效
    
    • android:layout_column=“2”: 表示跳过第二个,直接显示第三个,从1开始
    • android:layout_span=“4”:表示合并*4个单元格,也就说这个组件占4个单元格

    FrameLayout 帧布局

    FrameLayout布局在不使用layout_gravity属性的情况下,布局中的多项元素会在父容器的左上角重叠,使用layout_gravity 属性,可以设置不同的位置。

    在这里插入图片描述

    重要属性

    • top、bottom、left、right:将对象放在其容器的上、下、左、右的位置
    • center、center_vertical、center_horizontal:讲对象居中、水平居中、竖直居中
      在这里插入图片描述
      注意 :区分 “android:gravity”“android:layout_gravity”
      • android:gravity :是对控件本身而言,控制控件自身的内容在控件中的位置
      • android:layout_gravity:是相对于控件父容器而言,设置该控件在其父容器中的位置

    RelativeLayout 相对布局

    相对布局是用的比较多的一种布局。因为布局套用越多,布局加载越慢,如果使用相对布局,紧紧只需要一次布局。一般使用布局都是相对布局+线性布局使用。
    相对布局主要记住重要的属性

    此图来自:https://www.runoob.com/w3cnote/android-tutorial-relativelayout.html
    此图来自:https://www.runoob.com/w3cnote/android-tutorial-relativelayout.html

    注意marginpadding 的区别
    * margin:代表的是偏移,是相对于父容器而言
    * padding:代表的是填充,是本组件内部而言

    GridLayout 网格布局

    网格布局与TableLayout(表格布局)类似,不过网格布局功能更多,也更好用。

    • 可以设置布局中组件的排列方式
    • 可以设置网格布局有几行几列
    • 可以直接设置组件的位置,位于某行某列
    • 可以直接设置组件占多少行多少列

    使用网格布局,需要先设置排列方式、对齐方式、行数、列数。然后对布局中的子组件进行行列设置。
    在这里插入图片描述
    图片来自:https://blog.csdn.net/wangmx1993328/article/details/82770910

    下例是计算器布局:

    在这里插入图片描述

    <GridLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:columnCount="4"
            android:orientation="horizontal"
            android:rowCount="6">
            <TextView
                android:layout_columnSpan="4"
                android:layout_marginLeft="5dp"
                android:layout_marginRight="5dp"
                android:background="#ffcccccc"
                android:text="0"
                android:textSize="50sp"
                android:layout_gravity="fill" />
            <Button
                android:layout_columnSpan="1"
                android:text="1"
                android:layout_gravity="fill" />
            <Button
                android:text="2"
                android:layout_gravity="fill" />
            <Button
                android:text="3"
                android:layout_gravity="fill" />
            <Button
                android:text="+"
                android:layout_gravity="fill" />
    
            <Button
                android:layout_columnSpan="1"
                android:text="4"
                android:layout_gravity="fill" />
            <Button
                android:text="5"
                android:layout_gravity="fill" />
            <Button
                android:text="6"
                android:layout_gravity="fill" />
            <Button
                android:text="-"
                android:layout_gravity="fill" />
            <Button
                android:layout_columnSpan="1"
                android:text="7"
                android:layout_gravity="fill" />
            <Button
                android:text="8"
                android:layout_gravity="fill" />
            <Button
                android:text="9"
                android:layout_gravity="fill" />
            <Button
                android:text="*"
                android:layout_gravity="fill" />
            <Button
                android:layout_columnSpan="1"
                android:text=""
                android:layout_gravity="fill" />
            <Button
                android:text="0"
                android:layout_gravity="fill" />
            <Button
                android:text="="
                android:layout_gravity="fill" />
            <Button
                android:text="/"
                android:layout_gravity="fill" />
        </GridLayout>
    

    AbsoluteLayout 绝对布局

    绝对布局放在最后,是因为绝对布局基本上是不使用的。一般布局需要适配不同机型,如果使用绝对布局,在不同尺寸的手机上显示会变形。

    重要属性

    • android:layout_x:设置组件的x坐标
    • android:layout_y:设置组件的y坐标

    在这里插入图片描述

    <AbsoluteLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    
            <Button
                android:id="@+id/button1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_x="50dp"
                android:layout_y="100dp"
                android:text="=" />
    
            <Button
                android:id="@+id/button2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_x="150dp"
                android:layout_y="100dp"
                android:text="=" />
    
            <Button
                android:id="@+id/button3"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_x="100dp"
                android:layout_y="120dp"
                android:text="." />
    
        </AbsoluteLayout>
    
    展开全文
  • Android 五大布局

    千次阅读 2018-09-03 11:29:03
    五大布局分别是:LinearLayout(线性布局)、RelativeLayout(相对布局)、FrameLayout(帧布局)、TableLayout(表格布局)、AbsoluteLayout(绝对布局);比较常用的为前两个。 下面是简单介绍,主要还是靠自己...

    五大布局分别是:LinearLayout(线性布局)、RelativeLayout(相对布局)、FrameLayout(帧布局)、TableLayout(表格布局)、AbsoluteLayout(绝对布局);比较常用的为前两个。

    下面是简单介绍,主要还是靠自己练习。

    1.LinearLayout(常用,一般用于简单布局)

    特点:排列方式只有水平排列和垂直排列两种,orientation 设置为 horizontal 为水平排列, 设置为 verital 为垂直排列。

    2.RelativeLayout(常用,一般用于复杂布局)

    特点: RelativeLayout 中子 View 的排列方式是基于彼此的依赖关系。

    3.FrameLayout

    特点:布局简单,所有的子 View 都放在布局左上角,写在下面的 View 会覆盖 写在上面的 View。

    4.TableLayout

    特点:TableLayout继承自Linearout,本质上仍然是线性布局管理器,不需要明确地声明包含多少行、多少列;每向TableLayout中添加一个TableRow就代表一行;每向TableRow中添加一个一个子组件就表示一列。

    5.AbsoluteLayout (已过时)

    Android不提供任何布局控制,而是由开发人员自己通过X坐标、Y坐标来控制组件的位置。每个组件都可指定如下两个XML属性:layour_x;layout_y;

     

    更多好内容戳下面:

    https://blog.csdn.net/wuqingsen1

    展开全文
  • 人体五行

    千次阅读 2017-06-08 14:55:34
    五行人体图解  一、五行:   五行 特性 对应人体系统 对应管理系统 木 木能生火,被金所克 免疫系统 销售系统 火 火化为灰生土,被水所克 内分泌系统 营销系统 土 土凝聚生...

     
     

     
    五行人体图 - 亿能 - 亿能部落格---观察思维比思维本身更重要
     
    五行人体图 - 亿能 - 亿能部落格---观察思维比思维本身更重要
     
     

    五行人体图解

           一、五行:

     


    五行

    特性

    对应人体系统

    对应管理系统

    木能生火,被金所克

    免疫系统

    销售系统

    火化为灰生土,被水所克

    内分泌系统

    营销系统

    土凝聚生金,被木所克

    消化系统

    人力系统

    金下沉生水,被火所克

    呼吸系统

    财务系统

    水上升生木,被土所克

    循环系统

    技术系统


            

            二、五脏:

     


    五行

    特性

    对应管理部门

    比如将军,谋略从肝而出

    销售

    比如君主,智慧从心而出

    营销

    比如库官,营养从脾而出

    人力

    比如宰相,调节一身之气

    财务

    比如技师,技巧从肾而出

    技术


     

    三、五官:

     


    五官

    特性

    对应管理部门

    视:眼观六路,察颜观色

    需求

    味:品尝五味,滋津生液

    公关

    触:进食吐故,吸气交流

    接待

    溴:呼吸气体,一进一出

    收银

    听:耳听八方,只进不出

    咨询


     

    四、五表:

     


    五表

    特性

    对应管理部门

    瓜甲

    瓜甲的大小、圆润、颜色观察出肝的变化

    定位

    面部神情喜、乐、忧、愁观察出心的变化

    设计

    唇的大小、厚薄、干润、颜色观察脾的变化

    招聘

    毫毛

    毫毛的长短、粗细、浓淡观察出肺的变化

    出纳

    头发

    头发的干润、粗细、颜色观察出肾的变化

    规划


     

    五、五体:

     


    五体

    特性

    对应管理部门

    筋膜

    连接身体,伸缩舒畅

    客户

    血脉

    输送营养,滋养全身

    产品

    肌肉

    充实身体,吐故纳新

    培训

    皮毛

    保护身体,吸纳精气

    会计

    骨髓

    支撑身体,产生血液

    服务


     

    六、六腑:

     


    六腑

    特性

    对应管理部门

    清虚之器,分泌胆汁分解脂肪,具有决断力

    品牌

    小肠

    吸收之器,接受脾胃消化的食物进一步吸收

    策划

    仓库之器,五味对人体的滋养给用从胃产生

    行政

    大肠

    输送之器,食物消化、吸收、排泄大肠完成

    仓储

    膀胱

    水液之器,水液在膀胱聚集经过气化而排出

    维护


     

    根据人体经络和阴阳五行,脏腑之间的关系是什么?
    脏腑是中医对人体内部器官的总称,心、肝、脾、肺、肾为五脏,胃、胆、三焦、膀胱、大肠、小肠为六腑。
    心为人的气血根本,在阴阳五行中属火.能够推动和调节血脉,使血脉循行旺盛.还能影响一个人的思维活动和精神意识。并且与舌相通,帮助舌辨别饮食五味。肺是人体的生气之源,在阴阳五行中属金,管理人的呼吸.使清阳之气升发,浊阴之气减少,疏通和调节体内水液.辅助心脏,治理和渊节血液运行,还主呼吸。脾是血液生化之源,在阴阳五行中属土,能将食物精华送到全身,运化水湿浊气并排泄于体外,还能统摄血液,帮助肌肉生长;肝藏血,主管人体筋脉,在五行中属木,能够贮藏血液、调节血量。通气于目,并且主管筋脉,指甲的坚脆厚薄与颜色都是肝脏盛衰的表现。肾是人体先天之本.在五行中属水;能储藏人体精气,主宰人体的生长发育与生殖,维持体内水液代谢平衡,摄纳肺吸入的清气。防止呼吸表浅等。
    五脏主要是储藏精气津液。六腑则是出纳转输精气津液。虽然脏腑的功能不一样,但却相互依存,相互制约,形成一个完整的机体。脏与腑是表里互相配合,一脏配一腑,脏属阴,为里;腑属阳,为表。脏腑的表里是由经络联系的,即脏的经脉络于腑,腑的经脉络于脏,彼此经气相通,互相作用.所以,脏与腑在病变上能够互相影响,互相转变。
    脏腑不但能够在人体内部相互联系.而且同外界自然环境也有很大的关系。如果外部发生变化、四时气候转移、精神活动等都会影响到脏腑的联系。

    五脏:肝·心·脾·肺·肾 人体的实体性器官 生化并储存人体的精华 
    六腑:胆·小肠·胃·大肠·膀胱·肾  空体性器官,人体的输送管道消化食物并排除废物 
         木--肝脏·胆      主经络  开窍于眼对应春天绿色  春养肝胆 
         火--心脏·小肠  主血脉  开窍于舌  对应夏天  红色夏养心 
         土--脾脏·胃      脾胃是后天之本,气血升华之源黄色 一年四季 养脾胃 
         金--肺·大肠     主皮毛  开窍于鼻  对应秋天白色  秋养肺 
         氺--肾·膀胱     主骨髓  开窍于耳朵 对应冬天 黑色冬养肾 
    春养肝夏养心  秋养肺   冬养肾  一年四季养脾胃 
                                         
                                          人体十四经络运行穴位 
    肺经-(从胸到手)--中府-尺泽-列缺-少商 
    大肠经(从手到头)--商阳-合谷-曲池-臂臑-肩髃-迎香 
    胃经(从头到脚)--   承泣-四百-头维-人迎-缺盆-乳中-乳根-天枢-梁丘-足三里-解溪-历兑 
    脾经(从脚到胸)--  隐白--三阴交-阴陵泉-血海-大横-大包 
    心经(从胸到手)--  极泉-神门-少冲 
    小肠经(从手到头)--少泽-肩贞-天宗-听宫 
    膀胱经(从头到脚)--睛明-攒竹-天柱-承扶-殷门-委中-承山-昆仑-至阴 
    肾经(从脚到胸) --涌泉-太溪-阴谷-俞府 
    心包经(从胸到手)--天池-曲泽-郄门-内关-劳宫-中冲 
    三焦经(从手到头)--关冲-四渎-肩髎-翳风-耳门-丝竹空 
    胆经(从头到脚)--  瞳子髎-率骨-风池-肩井-带脉-环跳-风市-阳陵泉-足窍阴 
    肝经(从脚到胸)-- 大敦-行间-太冲-章门-期门 
    督脉(行气)--   腰俞-腰阳关-命门-脊中-至阳-身柱-大椎-风府-百会-神庭-人中-龈交 
    任脉(司血)--   承浆-廉泉-天突-膻中-鸠尾-中脘-神阙-气海-关元   

                                             十二时辰·经络·五脏六腑·养生 
    手三阴肺经 (1:oo_3:00)  肺部胀满·咳嗽气喘·缺盆及喉咙疼痛    ·宜调理肺经和熟睡 
    手三阳大肠经(5:00-7:00)牙齿痛痛·颈部肿大     ·宜喝温开水排便·调理大肠经 
    足三阳胃经(7:00-9:00)腹部长鸣·消化不良         ·宜及时吃早餐 调理胃经 
    足三阴脾经(9:00-11:00)舌根强直·食则呕吐胃脘疼痛腹内发胀适量饮水   ·调理脾经 
    手三阴心经(11:00-13:00)喉咙干燥头痛口渴难思  吃午餐 休息 静养阴血 ·调理心经 
    手三阳小肠经(13:00-15:00)喉咙 颔部痛 肩痛如裂臂痛如断  

    展开全文
  • 大家好,我是陈哈哈。认识我的朋友们知道,我是非科班出身,半路出家,大学也很差!这种背景来北漂,你都不知道你会经历什么????????

      大家好,我是陈哈哈。认识我的朋友们知道,我是非科班出身,半路出家,大学也很差!这种背景来北漂,你都不知道你会经历什么🙃🙃。
      如今虽没有风生水起,但在技术这块儿也算是有了些许发自内心的底气,去年和今年有幸得到了几个(< 3)普通大厂(非一线)的offer邀约。在这里多谢各位引路人,确实还没到时候,在此抱歉。

    在这里插入图片描述

      前车之鉴,后事之师。希望我的文章们能帮助你少走些弯路。打工人不易,加油!

      今天想把我的一些真实的小故事分享给大家,包括我的菜鸡学生时代 → 入行 → 现在,以及工作五年结合亲身经历的一些忠告。如果对你有用,请记得分享给你的朋友们!

    一、六年前的LOL电一大师,六年后的北漂程序员

      从高中(s1)到大学(s7)打了7年的LOL,电一大师、网一王者,一度准备打职业。多的不再赘述,要知道,那些除了纪念和情怀,对我都不再有意义。

      难以启齿,LOL算是陪伴了我的半个青春,因此我对它的情怀冲淡了他对我职业生涯的伤害。去年我挤地铁时看到了s10总决赛,才发现我已经快4年不曾想起过这个游戏。甚至突然想写一篇文章叫《六年前的LOL电一大师,六年后的北漂程序员》,太有感觉了,脸上发热,我越写越投入,好像激活了心底尘封多年的一些记忆。我恍然发现自己曾经也是那个奔跑在阳光下的少年,有梦想。有一起拼命奔跑的朋友,时常因训练失误我们全队人不吃饭一起惩罚。

      但我停笔了,不愿再回忆那段往事。唉,或许你也知道那种感觉。

    在这里插入图片描述

      是的,我怕回不来,回不到这个真实的社会、职场。自己接受不了,分不清这个社会到底给我们这代人带来了什么。。就像我来北京前最后一个晚上,改名为:忙碌充斥回忆。

    分享我最喜欢的一句台词:

    我曾踏足山巅,也曾坠入低谷,二者都使我获益良多。 ---- 塔里克

    二、刚入门时的苦,只有熬下来的人知道

      出来混的都不容易,刚入门时的苦,只有熬下来的人知道。

      半路出家嘛,你知道的。

      大家坐到一起的都是朋友,一开始三四十位同学,现在还有消息的,不到十位了。

      都是如出一辙的身世。但,既然选择入这行,态度至关重要,凭本事吃饭,如果只冲着混个工作去的,我建议你还是耗子尾汁。

    在这里插入图片描述
      我属于没有天赋型的,一开始咱啥也不会,听啥都模模糊糊的,似懂非懂,很多知识点都学到那种意会了但不能言传的水准😆😆,一度还挺自信的~~后来我知道,其实这就是不懂🙃!那半年我和几个朋友每天早上7点到8点和部队的大爷们打蓝球,然后上课,晚上坐到九点多看门的大爷来撵人,周末一天必须回顾一周学的知识,尽量搞点东西出来。

      周六我休息一天,这天我喜欢找个角落看看视频,看看博客,体验一把程序员996生活的那一抹闲暇。

      直到拿了两个offer下山。

      希望刚入坑的同学们明白:不要以看完多少课时为目标,或晚上学到几点为榜样。

    三、五年程序员生涯,给你的一些建议

    北漂五年了。岁月如梭,不是么?

      坦白说,其实这里才是我想和你分享的第一段内容。

      希望你理解,毕竟,人到中年,总会容易勾起很多过往。像每当夜晚下班经过后厂村路时,哼起那首熟悉的歌谣,“春风不解风情,吹动少年的心~ 让昨日脸上的泪痕,随记忆风干了”

    1、与人交谈比与机器交谈更重要

      编程是一项团队运动!

      现在早已不是那个一把刀闯天下的年代了,更多是需要多元化技术团队的整合,才能够创造出一个出色的产品。

      沟通技巧可以成就一个项目,也可能会毁了它。相比存粹的技术,软技能对一个项目的成功起到更重要的作用。我们需要学习如何与不同的人有效地交流我们的想法和思想,以解决我们(作为一个团队)面临的问题。

      就像我常常和同事们开玩笑说,每当我遇到难攻克的技术难题,我都会买两瓶可乐去找产品,和他一起抽根烟,打会儿球,谈谈人生理想,往往能解决我难以解决的问题。
    在这里插入图片描述

    2、知晓你在做什么以及为什么这么做

      人一旦有了明确目标,效率和主动性会明显提高,就像我每每深夜读完鸡汤文,我就睡不着。其实,在工作中也是一样的。

      作为软件开发人员,你的目标不应该只是把 JIRA 转换成 JavaScript,或者把 Github 中的开源项目合到你的 Java 程序中。

      你的目标应该是用代码来解决问题。

      如果你对要构建/维护的系统有深刻的了解,则可以在纯技术之外做出决策。这个功能是必需的吗?它解决了什么问题?可以用其他方式来解决这个问题吗?真的有必要解决这个问题吗?在强调一下,有时解决问题是不需要任何代码的,你懂我意思的。。

    在这里插入图片描述

      这种思路有时被称之为业务环境,如果你想把工作做好,不仅应该了解项目情况如何,还应该能够塑造和影响环境。即使你在公司里不是Leader,也不影响你这么做,至少,你要明白自己在做什么。

      你的领导会看到你和其他的同事不一样,肯定是优于他们的。

    3、防患于未然

    墨菲定律:会出错的事情就一定会出错。

      这是太真实的事情之一了。设计系统时,我们要始终假定某些东西可能会损坏。

      比如开发登录表单提交功能时,要假设用户会把百度里的任意一篇博客或一堆符号粘贴到你的密码输入栏中。

      如果系统中使用了数据库,它一定会在某个时刻挂掉。如果你没有尝试过使用你的binlog日志或延迟从库等途径的备份来恢复数据库,那它们就算不上是备份!比如和你对接的那个前辈对你说“别想太多,不可能宕机”这种话,别信他的,记住一定要找他问清楚,搞清楚里面有哪些坑。否则,真正出现这个问题的时候,你只能做好跑路或背锅的打算。
    在这里插入图片描述

      如果你在给客户做演示,请确保这个演示在任何情况下都能正常进行,哪怕是同事把服务器电源拔了!我经历过在会议室演示时,公司wifi断了,连不上服务器。客户和老板吃着西瓜等我恢复,运维告知我一时半会儿恢复不了。

      坦白说这种情况完全可以甩锅给公司网络组,但是锅不能让老板背吧?于是怎么着,我叫运维把服务器从机房运到会议室旁,拉一条网线继续演示。如果你是老板,会咋想呢?

    4、别害怕让别人看到自己的一无所知

      我们曾如此渴望命运的波澜,到最后才发现:人生最曼妙的风景,竟是内心的淡定与从容……我们曾如此期盼外界的认可,到最后才知道:世界是自己的,与他人毫无关系。 – 《一百岁感言》杨绛

      这里用杨绛先生的话来当引子,作为一位工作多年的资深程序员,当别人问一些我不懂的问题时,我可以很淡然地告诉他们:这个东西我也不懂,因为以前没有遇到过,不过我可以看一下,然后再告诉你。这样也会让他们感到被尊重。

      当我还是一个初级程序员的时候,我总是很害怕别人会看到我的无知。经过几年的磨练,我才明白,如果碰到了自己不懂的东西,说明学习的机会来了。终身学习绝对不只是一个“口头禅”。

    5、学会分享

      等你把不懂的东西搞懂了,记得把它们分享出来。写一篇博客,录个教学视频,或者有机会能在公司里搞个分享演讲……你不要认为你刚学会的东西别人也都懂,即使是一个非常资深的人,他们也能从初级人员身上学到东西,反过来也是。

      分享的过程其实是一个检验你是否真正理解所学的东西的过程。要知道,当你在教一个人的时候,其实有两个人在学。

    记得早先在一个问答中问到:

    你的编程能力从什么时候开始突飞猛进的?

      有个令我印象很深的回答:突飞猛进往往是自然发生的。你在某个夜晚苦熬一个知识点时,不会觉得自己突飞猛进;只有在多年后某日熟练地给别人讲解这个知识点后,内心才会小小地波动一下,猛然忆起当年深夜中的青灯一盏。

      共勉。

      看到这里,我想你也是个有故事的程序员,请不要吝啬你的赞个收藏哦!

    展开全文
  • 五大常用算法之三:贪心算法

    万次阅读 2018-03-14 13:11:26
     贪心算法还是很常见的算法之一,这是由于它简单易,构造贪心策略不是很困难。  可惜的是,它需要证明后才能真正运用到题目的算法中。  一般来说, 贪心算法的证明围绕着:整个问题的最优解一定由在贪心策略中...
  • 在目前的站长圈内,比较流行的采集工具有很多,但是总结起来,比较出名的免费的就这么几个:火车头,海纳,ET,三人,狂人。 下面我们对这几款采集工具作一个简单的评比。 1.火车头 基本上人人都知道,那就放第...
  • 详谈五大主流浏览器

    千次阅读 2019-12-03 19:57:54
    为什么是五大浏览器 市场份额 有自己独特的内核(渲染引擎+js引擎) 五大浏览器的区别 独特的解释语法(FireFox最接近ECMA的标准) 渲染效果不同 性能不一样,支持脚本的执行速度等不一样 简单介绍一下五大...
  • 五大常用算法

    万次阅读 多人点赞 2018-10-05 07:13:50
    五大常用算法   分治算法   一、基本概念  在计算机科学中,分治法是一种很重要的算法。字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题...
  • 文章目录人体的基本五行 - 心肝脾肺肾,金木水火土 对应关系与基础解读1、对应关系2、重要性3、五行的相生相克关系4、五官5、情志6、一些解读7、一些案例 人体的基本五行 - 心肝脾肺肾,金木水火土 对应关系与基础...
  • 五大常用经典算法

    万次阅读 多人点赞 2014-09-14 18:32:24
    五大常用算法之一:分治算法
  • 影响MySQL性能的五大配置参数

    千次阅读 2014-03-02 21:32:38
    我们今天主要和大家分享的是对MySQL性能影响关系紧密的五大配置参数,以下就是文章的具体内容描述,希望会给你带来一些帮助。 以下的文章主要是对MySQL性能影响关系紧密的五大配置参数的介绍,我前几天在相关网站...
  • 五大常用算法之回溯法

    千次阅读 2014-06-29 16:24:25
    看了五大常用算法之一这篇博文,感觉理解了很多,可是纯粹都是理论,缺少一些示例,所以准备综合一篇博文,以帮助自己记忆,原文: http://www.cnblogs.com/steven_oyj/archive/2010/05/22/1741376.html
  • 浏览器五大内核

    万次阅读 2018-09-04 12:51:54
    迸发了一种凤凰涅槃的快感,到今天为止Firefox也成为了五大主流之一,后面我们再说它~话说回来,竞争才能推动技术的发展,第一次浏览器大战以微软和网景为代表,大力推动了浏览器方面技术的发展,各大公司开始着手...
  • 五大经典算法总结

    万次阅读 多人点赞 2018-08-21 11:34:13
     五大经典算法分为 1、分治法:把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。 2、动态规划法:每次...
  • Facebook三大愿景和五大核心价值

    千次阅读 2017-09-05 10:57:00
    文章讲的是Facebook三大愿景和五大核心价值,Facebook2月2日启动IPO(首次公开招股),计划融资50亿美元。该公司创始人、CEO马克·扎克伯格发表公开信,点明Facebook的三大愿景和五大核心价值。  以下为公开信全文: ...
  • 五行属性查询

    千次阅读 2011-08-24 18:02:06
    甲子年生海中金命(1924,1984)乙丑年生海中金命(1925,1985) 丙寅年生炉中火命(1926,1986)丁卯年生炉中火...戊辰年生林木命(1928,1988)己巳年生林木命(1929,1989) 庚午年生路旁土命(1930,1990)辛
  • Android存储五大方式

    千次阅读 2016-08-29 11:03:13
    Android存储五大方式: 1 使用SharedPreferences存储数据  2 文件存储数据  3 SQLite数据库存储数据  4 使用ContentProvider存储数据 5 网络存储 (转载请标明出处,谢谢) 第一种: ...
  • 浅析ADO.NET五大对象

    千次阅读 热门讨论 2016-04-12 23:19:33
    引言在数据库应用系统中,必定要涉及到对数据库的访问和操作,而ADO.NET则是微软在.NET Framework中负责数据访问的类的库集,那么理清ADO.NET中的五大对象对于我们理解ADO.NET无疑会有很大的帮助。本文将对ADO.NET做...
  • SQL语言分为五大

    万次阅读 2018-08-11 12:41:40
    SQL语言分为五大类: DDL(数据定义语言) - Create、Alter、Drop 这些语句自动提交,无需用Commit提交。(Data Definition Language) DQL(数据查询语言) - Select 查询语句不存在提交问题。DML(数据操纵语言) - ...
  • JDK12的五大重要新特性

    万次阅读 2019-11-07 08:58:46
    文章目录JDK12的五大重要新特性引入JVM常量API扩展了switch语句支持Unicode 11.0为日本Reiwa Era提供了方形字符支持NumberFormat增加了对以紧凑格式格式化数字的支持 JDK12的五大重要新特性 Java12在March 19, 2019...
  • 武当太乙五行

    千次阅读 2008-09-17 16:22:00
    健身功效 [编辑本段] 武当太乙五行拳以整体柔韧之劲,制人之动,克人之刚 ! ! 从武当太乙五行拳架势和理论上分析。 武当太乙五行拳 (亦称武当太乙五行擒扑二十三式),是武当武术的主要拳种之一。此拳系明弘治(孝...
  • 中国五大物联网平台优势分析

    千次阅读 2018-03-05 21:40:52
    简介近几年物联网已经成为各各业和资本争相追逐的风口,进入2018年,物联网热度持续不减,一个全球化的智能互联时代即将到来。近几年物联网已经成为各各业和资本争相...为此OFweek物联网小编搜集了国内五大物...
  • 人格的五大模型

    千次阅读 2014-07-22 16:20:43
    在组织行为学里有好多对人格特质进行描述的模型,其中比较有名的一个是大五模型(维度人格模型)。 在大五模型里用个因素来考察人格特质:   外倾性(extroversion): 外倾者者倾向于喜欢群居,善于...
  • 三、五大约束: 数据库中的五大约束包括: 1.主键约束(Primay Key Coustraint) 唯一性,非空性; 2.唯一约束 (Unique Counstraint)唯一性,可以空,但只能有一个; 3.默认约束 (Default Counstraint) 该数据的...
  • ADO.NET的五大对象

    万次阅读 热门讨论 2016-07-05 09:50:08
    其中最重要的是它的五大对象,如下图所示:  应用程序和数据库之间的连接访问过程: 下面详细介绍一下每个对象:  Connection对象:  这个我在上篇博客已经介绍过:链接  Command对象:  主要...
  • 五大常用算法之二:动态规划算法

    万次阅读 2018-03-14 12:52:53
    、算法实现的说明  动态规划的主要难点在于理论上的设计,也就是上面4个步骤的确定,一旦设计完成,实现部分就会非常简单。  使用动态规划求解问题, 最重要的 就是 确定动态规划三要素 :  (1)问题的阶段 ...
  • 听梁肇新讲-阴阳五行原理

    万次阅读 热门讨论 2008-07-29 18:17:00
    3.梁肇新对中国传统术学研究颇多,擅长命理八字和玄空风水,给我们讲解了一番阴阳五行基本原理4.阴阳五行原理是古代先贤的基础理论,所有地方都可以看到这些理论的应用。基本上相当于欧几里德几何学在数学中的地位和...
  • AGI:走向通用人工智能的【生命学&哲学&科学】第一篇——生命、意识、五行、易经、量子 经典的物理统一在原子上,量子的物理统一在量子上,化学统一在元素上,而生命统一在DNA上,DNA本身拆干了,其实就是一群元素,...
  • 五大常用算法学习笔记

    万次阅读 多人点赞 2019-02-26 21:52:52
    分治算法:快速排序、归并排序、整数乘法、二分查找、递归(汉诺塔) 基本概念:把一个复杂的问题分成若干个相同或相似的子问题,再把子问题分成更小的子问题… , 知道最后子问题可以简单的直接求解,原问题的解...
  • Android之四大组件、六大布局、五大存储

    万次阅读 多人点赞 2016-09-06 16:15:36
    表格布局采用、列的形式来管理UI组件,并不需要明确地声明包含多少、多少列,而是通过添加TableRow、其他组件来控制表格的行数和列数。 每向TableLayout中添加一个TableRow就代表一; 每向TableRow...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 894,642
精华内容 357,856
关键字:

五大行比较