A Summary of Some Knowledge Points on Android and Java

Posted by gyoung on Sat, 25 May 2019 22:46:33 +0200

1. How to empty StringBuffer variable content in JAVA

StringBuffer my_StringBuffer = new StringBuffer();

my_StringBuffer.append('helloworld'); // Add strings to StringBuffer

Int sb_length = my_StringBuffer. length ();// Gets the length of the string
my_StringBuffer.delete(0,sb_length); //Delete the content of the string from 0 to sb_length-1 (this method is used to clear the content in StringBuffer)

There's another way.
my_StringBuffer.setLength(0); // Set the length of StringBuffer variable to 0

2. Relative layout and frame layout default child controls in the upper left
3. Textual Description of the Meaning of getX, getRawX and getTranslationX

See blog specifically: http://blog.csdn.net/dmk877/article/details/51550031

event.getX(): Represents the distance between the touching point and its left boundary.
event.getY(): Represents the distance between the touching point and its upper boundary.
event.getRawX: Represents the distance between the touch point and the left edge of the screen.
event.getRawY: Represents the distance between the touch point and the screen boundary.
View.getWidth(): Represents the width of the current control, namely getRight()-getLeft()

View.getHeight(): Represents the height of the current control, namely getBottom()-getTop()
View.getTop(): The distance from the top of the child View to the top of the parent View
View.getRight(): The distance from the right boundary of the child View to the left boundary of the parent View
View.getBottom(): The distance from the bottom of the child View to the top of the parent View
View.getLeft(): The distance from the left boundary of the child View to the left boundary of the parent View
View.getTranslationX() calculates the offset of the View on the X axis. The initial value is 0, the left offset value is negative, and the right offset value is positive.
View.getTranslationY() calculates the offset of the View on the Y axis. The initial value is 0, and the upward migration is negative, as evidenced by the downward migration.

4. Solutions to the drawerleft set in Button that is too far from the text:
It can be set by attributes.
Android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text = "chicken stewed mushroom"
android:textAlignment="textStart"
android:layout_gravity="start"
android:drawableLeft="@android:drawable/ic_menu_search"
Prior to version 17
You need to add it to the button
android:textAlignment="textStart"
android:layout_gravity="start"
After version 17
android:textAlignment="textStart"

5.android can set Padding for control in code, but can't set margin. According to margin's understanding, we need to refer to the principle of parent control, so we can't set it for children and sisters. We need to do the following:
There is setPadding in Android's view, but there is no direct setMargin method. What if you want to set it in your code?

You can set the LayoutParams settings in the view, which differs according to the view in different GroupView s.

ImageView image = (ImageView) findViewById(R.id.main_image);  
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(image.getLayoutParams());  //This is determined by the layout of the parent control of the current control.
lp.setMargins(50, 100, 0, 0);  
image.setLayoutParams(lp);  

The Relative Layout here means that the view is in a Relative Layout.

You can encapsulate the way you set margin as a method, as long as it's Layout Params in GroupView.

[java] view plain copy

public static void setMargins (View v, int l, int t, int r, int b) {  
    if (v.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) {  
        ViewGroup.MarginLayoutParams p = (ViewGroup.MarginLayoutParams) v.getLayoutParams();  
        p.setMargins(l, t, r, b);  
        v.requestLayout();  
    }  
}  

by the way
Padding is an inner border, referring to the internal content of the control, such as text/picture distance from the edge of the control.

Margin is the outer border, which refers to the distance between the control and the parent control.
6. The difference between using new Instance and using new is that the way to create objects is different. The former uses class loading mechanism. So why are there two ways to create objects? This is explained in terms of software ideas such as scalability, extensibility and reusability. Factory patterns in Java often use newInstance to create objects, so you can also find specific answers to why factory patterns are used.
For example:
Class c = Class.forName("A");
factory = (AInterface)c.newInstance();
Among them, AInterface is the interface of A. If you write this below, you may understand:
String className = "A";
Class c = Class.forName(className);
factory = (AInterface)c.newInstance();
Further, if you write below, you may understand:
String className = readfromXMlConfig; // Get string from xml configuration file
Class c = Class.forName(className);factory = (AInterface)c.newInstance();
The above code eliminates the name of class A. The advantage is that no matter how the class A changes, the above code remains unchanged, and even can replace the brothers of class A, B, C, D. Wait, as long as they inherit Ainterface.
From the point of view of jvm, when we use new, the class that wants new can not be loaded.
But when using new Instance, we must ensure that: 1. This class has been loaded; 2. This class has been connected. The static method forName () of class, which completes the above two steps, calls the boot class loader (the loader that loads the Java API).
With the understanding on the jvm above, we can say that newInstance actually decomposes the new approach into two steps: first, loading a class by calling its load method, and then instantiating it.
The benefits of this step-by-step approach are obvious. We can get more flexibility when we call class's static loading method forName, which provides us with a means of decoupling.

[supplement:]
New Instance: Weak type. Poor efficiency. Only parametric constructs can be invoked.
new: Strong type. Relatively efficient. Any public construct can be invoked.
new Instance () is an inevitable choice to implement IOC, reflection, inversion dependence and other technical methods. new can only realize the instantiation of specific classes, which is not suitable for interface programming. Inside the class, an object is constructed by the default constructor of the class, InstantiationException is thrown if there is no default constructor, IllegalAccessException is thrown if there is no access to the default constructor.

7. The difference between startActivity ForResult and startActivity is that:
1,startActivity( )
Just jump to the target page. If you want to jump back to the current page, you must use startActivity() again.
2,startActivityForResult( )
This task can be accomplished at one time. If the program jumps from T1 Activity to the next Text2Activity, when the Text2Activity calls the finish() method, the program automatically jumps back to T1Activity and calls the onActivityResult() method in the previous T1Activity.

The correlation function:
startActivityForResult(Intent intent, Int requestCode)
setResut(int resultCode, Intent intent)
onActivityResult(int requestCode, int resultCode, Intent intent)

A brief example is given.

1. Start Activity ForResult (intent, 0) is not used for jumping.
Copy code

Intent intent=new Intent();
intent.setClass(A.this, B.class);
Bundle bundle=new Bundle();
String str1="aaaaaa";
bundle.putString("str1", str1);
intent.putExtras(bundle);
Start Activity ForResult (intent, 0); // Start Activity ForResult is used here to do jumps, 0 here is a basis, you can write other values, but must >= 0

Copy code

2. Rewrite the onActivityResult method to receive data returned by B.
Copy code

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Switch (resultCode) {// resultCode is the marker for the return, and what I return in B is RESULT_OK.
case RESULT_OK:
Bundle b=data.getExtras(); //data is the Intent returned in B
String str=b.getString("str1"); //str is the value returned
break;
default:
break;
}
}

Copy code

3. The setResult method is used when returning data in B, and then the finish method is called.

setResult(RESULT_OK, intent); //intent is an intent with Bundle from A, of course, you can also define a new Bundle yourself.
finish(); // Make sure that the finish() method is called here

When is setResult() of Android activity called (emphasis and difficulty)

If set Result is set in the Activity of startActivityForResult, the result will not be returned to parent's Activeness immediately. Only when the current Activity is finish ed, the result will be sent to parent's onActivityResult to process!

If an activity wants to return data to the activity that started it, it can call the setResult() method. When do you call setResult() to return data?
Look at the source code and see:
Copy code

public final void setResult(int resultCode, Intent data) {
synchronized (this) {
mResultCode = resultCode;
mResultData = data;
}
}

public void finish() {
    if (mParent == null) {
        int resultCode;
        Intent resultData;
        synchronized (this) {
            resultCode = mResultCode;
            resultData = mResultData;
        }
        if (Config.LOGV) Log.v(TAG, "Finishing self: token=" + mToken);
        try {
            if (ActivityManagerNative.getDefault()
                .finishActivity(mToken, resultCode, resultData)) {
                mFinished = true;
            }
        } catch (RemoteException e) {
            // Empty
        }
    } else {
        mParent.finishFromChild(this);
    }
}

Copy code

This code shows that activity returns result when it is finished, which means that the call to setResult() method must precede finish().
Then if setResult() is called in the following methods, it may not return success: onPause(), onStop(), onDestroy().
Because these method calls do not necessarily precede finishes, of course the setResult call in onCreate() must precede finishes.

Press the BACK key to exit from an Activity. Once you press BACK, android automatically calls the Activity finish() method, and then sets the resultCode to RESULT_CANCELED, which will not return any data.
The solution is to capture BACK events in Activity, set Result first, and then call finish yourself, and you're done... Directly swallowed up the BACK incident itself.
Copy code

@Override
public void onBackPressed() {
Log.i(TAG, "onBackPressed");
setResult(Const.LIVE_OK);
super.onBackPressed();
}

Copy code

Of course, you can call setResult on onCreate(), but I don't think it's a good way to override the onBackPressed() method.

8. Extract the file name from the path:
public String getFileName(String pathandname){

    int start=pathandname.lastIndexOf("/");    
    int end=pathandname.lastIndexOf(".");    
    if(start!=-1 && end!=-1){    
        return pathandname.substring(start+1,end);      
    }else{    
        return null;    
    }    

}   

9.Bitmap:

 Bitmap is one of the most important classes of image processing in Android system. It can obtain image file information, perform image clipping, rotation, scaling and other operations, and can save image file in specified format.

Important function

 public void recycle() // Recycle the memory space occupied by bitmaps and mark them Dead

 public final boolean isRecycled() //Determine whether bitmap memory has been freed  

 public final int getWidth()//Get the width of the bitmap 

 public final int getHeight()//Getting the Height of Bitmap

 public final boolean isMutable()//Is the picture modifiable 

 public int getScaledWidth(Canvas canvas)//Gets the width of the converted image with the specified density 

 public int getScaledHeight(Canvas canvas)//Get the height of the converted image with the specified density 

public boolean compress(CompressFormat format, int quality, OutputStream stream)//Converts the image to an output stream according to the specified image format and quality. 

format: Bitmap.CompressFormat.PNG or Bitmap.CompressFormat.JPEG 

quality: Picture quality, 0-100.0 Represents the lowest quality compression, 100 with the highest quality compression. about PNG This setting will be ignored for images in lossless format.

public static Bitmap createBitmap(Bitmap src) //Using src as the original image to generate immutable new images 

public static Bitmap createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter)//Using src as the original image, create a new image, specify the height and width of the new image and whether it can be changed. 

public static Bitmap createBitmap(int width, int height, Config config)-Create bitmaps of specified format and size 

public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height)with source Create a new image for the original image, specify the starting coordinates and the width and height of the new image.

BitmapFactory class:
Option parameter class:

public boolean inJustDecodeBounds//If set to true, no pictures are obtained, no memory is allocated, but the height and width information of the picture is returned.

public int inSampleSize//Multiplication of image scaling

public int outWidth//Get the width value of the picture

public int outHeight//Get the height of the picture 

public int inDensity//Pixel Compression Ratio for Bitmaps 

public int inTargetDensity//Pixel compression ratio for target bitmap (bitmap to be generated) 

public byte[] inTempStorage //Create temporary files to store images

public boolean inScaled//Image compression when set to true, from in Density to in Target Density

public boolean inDither //If true, the decoder attempts to jitter decoding

public Bitmap.Config inPreferredConfig //Setting Decoder

public String outMimeType //Setting Decoded Image

public boolean inPurgeable//Can the memory space stored in Pixel be reclaimed when there is insufficient memory in the system?

public boolean inInputShareable //If inPurgeable is true, is it possible to share an InputStream?

public boolean inPreferQualityOverSpeed  //For true, the quality of Bitmap is guaranteed first, followed by decoding speed.

public boolean inMutable //Can the configuration of Bitmap be changed, such as adding a line segment every few pixels on Bitmap?

public int inScreenDensity //Pixel density of the current screen

Factory method:

public static Bitmap decodeFile(String pathName, Options opts) //Read pictures from files 

public static Bitmap decodeFile(String pathName)

public static Bitmap decodeStream(InputStream is) //Read pictures from the input stream

public static Bitmap decodeStream(InputStream is, Rect outPadding, Options opts)

public static Bitmap decodeResource(Resources res, int id) //Read pictures from resource files

public static Bitmap decodeResource(Resources res, int id, Options opts) 

public static Bitmap decodeByteArray(byte[] data, int offset, int length) //Read pictures from arrays

public static Bitmap decodeByteArray(byte[] data, int offset, int length, Options opts)

public static Bitmap decodeFileDescriptor(FileDescriptor fd)//Reading files from files is different from decodeFile in that it is more efficient to call JNI functions directly.

public static Bitmap decodeFileDescriptor(FileDescriptor fd, Rect outPadding, Options opts)

Bitmap.Config inPreferredConfig :

 Enumeration variables (the higher the bitmap number, the more color information it can store, the more realistic the image, and the more memory it occupies)

public static final Bitmap.Config ALPHA_8// Represents 8-bit Alpha bitmaps. Each pixel occupies 1 byte of memory.
public static final Bitmap.Config ARGB_4444// Represents 16-bit ARGB bitmaps. Each pixel occupies 2 byte of memory.
public static final Bitmap.Config ARGB_8888// Represents 32-bit ARGB bitmaps. Each pixel occupies 4 byte of memory.
public static final Bitmap.Config RGB_565// Represents 8-bit RGB bitmaps. Each pixel occupies 2 byte of memory.

 The memory occupied by a picture (BitMap) in Android is mainly related to the following factors: the length of the picture, the width of the picture, and the number of bytes per pixel. Memory occupied by a BitMap = image length * image width * bytes occupied per unit pixel

Examples of picture reading:
1. Reading from files
Copy code

/**
* Get the scaled local image
*
*@ param filePath file path
*@ param width
*@ param height
* @return
*/
public static Bitmap readBitmapFromFile(String filePath, int width, int height) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePath, options);
float srcWidth = options.outWidth;
float srcHeight = options.outHeight;
int inSampleSize = 1;

    if (srcHeight > height || srcWidth > width) {
        if (srcWidth > srcHeight) {
            inSampleSize = Math.round(srcHeight / height);
        } else {
            inSampleSize = Math.round(srcWidth / width);
        }
    }

    options.inJustDecodeBounds = false;
    options.inSampleSize = inSampleSize;

    return BitmapFactory.decodeFile(filePath, options);
}

Copy code
2. The efficiency of mode 2 is higher than that of mode 1.
Copy code

/**
* Get the scaled local image
*
*@ param filePath file path
*@ param width
*@ param height
* @return
*/
public static Bitmap readBitmapFromFileDescriptor(String filePath, int width, int height) {
try {
FileInputStream fis = new FileInputStream(filePath);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFileDescriptor(fis.getFD(), null, options);
float srcWidth = options.outWidth;
float srcHeight = options.outHeight;
int inSampleSize = 1;

        if (srcHeight > height || srcWidth > width) {
            if (srcWidth > srcHeight) {
                inSampleSize = Math.round(srcHeight / height);
            } else {
                inSampleSize = Math.round(srcWidth / width);
            }
        }

        options.inJustDecodeBounds = false;
        options.inSampleSize = inSampleSize;

        return BitmapFactory.decodeFileDescriptor(fis.getFD(), null, options);
    } catch (Exception ex) {
    }
    return null;
}

Copy code

The test also generates 10 pictures in two ways. Comparing the cpu usage and memory usage, the second way is more efficient, so it is recommended that the second way be preferred.
Copy code

  start = System.currentTimeMillis();
    for (int i = 0; i < testMaxCount; i++) {
        BitmapUtils.readBitmapFromFile(filePath, 400, 400);
    }
    end = System.currentTimeMillis();
    Log.e(TAG, "BitmapFactory decodeFile--time-->" + (end - start));

    start = System.currentTimeMillis();
    for (int i = 0; i < testMaxCount; i++) {
       BitmapUtils.readBitmapFromFileDescriptor(filePath, 400, 400);
    }
    end = System.currentTimeMillis();
    Log.e(TAG, "BitmapFactory decodeFileDescriptor--time-->" + (end - start));

Copy code

3. Read files from input stream
Copy code

/**
* Get the scaled local image
*
*@ param ins input stream
*@ param width
*@ param height
* @return
*/
public static Bitmap readBitmapFromInputStream(InputStream ins, int width, int height) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(ins, null, options);
float srcWidth = options.outWidth;
float srcHeight = options.outHeight;
int inSampleSize = 1;

    if (srcHeight > height || srcWidth > width) {
        if (srcWidth > srcHeight) {
            inSampleSize = Math.round(srcHeight / height);
        } else {
            inSampleSize = Math.round(srcWidth / width);
        }
    }

    options.inJustDecodeBounds = false;
    options.inSampleSize = inSampleSize;

    return BitmapFactory.decodeStream(ins, null, options);
}

Copy code
4. Read files from resource files
Copy code

public static Bitmap readBitmapFromResource(Resources resources, int resourcesId, int width, int height) {
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(resources, resourcesId, options);
    float srcWidth = options.outWidth;
    float srcHeight = options.outHeight;
    int inSampleSize = 1;

    if (srcHeight > height || srcWidth > width) {
        if (srcWidth > srcHeight) {
            inSampleSize = Math.round(srcHeight / height);
        } else {
            inSampleSize = Math.round(srcWidth / width);
        }
    }

    options.inJustDecodeBounds = false;
    options.inSampleSize = inSampleSize;

    return BitmapFactory.decodeResource(resources, resourcesId, options);
}

Copy code

It is recommended that decodeStream be used instead of decodeResource, which is quite memory-intensive in this way.
Copy code

public static Bitmap readBitmapFromResource(Resources resources, int resourcesId, int width, int height) {
    InputStream ins = resources.openRawResource(resourcesId);
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeStream(ins, null, options);
    float srcWidth = options.outWidth;
    float srcHeight = options.outHeight;
    int inSampleSize = 1;

    if (srcHeight > height || srcWidth > width) {
        if (srcWidth > srcHeight) {
            inSampleSize = Math.round(srcHeight / height);
        } else {
            inSampleSize = Math.round(srcWidth / width);
        }
    }

    options.inJustDecodeBounds = false;
    options.inSampleSize = inSampleSize;

    return BitmapFactory.decodeStream(ins, null, options);
}

Copy code

DecdeStream, decodeResource occupy memory comparison:
Copy code

start = System.currentTimeMillis();
for (int i = 0; i < testMaxCount; i++) {
BitmapUtils.readBitmapFromResource(getResources(), R.mipmap.ic_app_center_banner, 400, 400);
Log.e(TAG, "BitmapFactory decodeResource–num–>" + i);
}
end = System.currentTimeMillis();
Log.e(TAG, "BitmapFactory decodeResource–time–>" + (end - start));

    start = System.currentTimeMillis();
    for (int i = 0; i < testMaxCount; i++) {
        BitmapUtils.readBitmapFromResource1(getResources(), R.mipmap.ic_app_center_banner, 400, 400);
        Log.e(TAG, "BitmapFactory decodeStream--num-->" + i);
    }
    end = System.currentTimeMillis();
    Log.e(TAG, "BitmapFactory decodeStream--time-->" + (end - start));

Copy code

Pictures loaded by BitmapFactory.decodeResource may be scaled. The scaling is currently done in the java layer, which is inefficient and consumes the memory of the java layer. Therefore, it is easy to cause OOM errors if images are loaded with this interface in large quantities.

BitmapFactory.decodeStream does not zoom in on the loaded image, which takes up less memory and is more efficient.

These two interfaces have their own uses, decodeStream should be used if the performance requirements are high, and decodeResource can be used if the performance requirements are not high and Android's own image adaptive zooming function is required.
5. Read pictures from binary data
Copy code

public static Bitmap readBitmapFromByteArray(byte[] data, int width, int height) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(data, 0, data.length, options);
float srcWidth = options.outWidth;
float srcHeight = options.outHeight;
int inSampleSize = 1;

    if (srcHeight > height || srcWidth > width) {
        if (srcWidth > srcHeight) {
            inSampleSize = Math.round(srcHeight / height);
        } else {
            inSampleSize = Math.round(srcWidth / width);
        }
    }

    options.inJustDecodeBounds = false;
    options.inSampleSize = inSampleSize;

    return BitmapFactory.decodeByteArray(data, 0, data.length, options);
}

Copy code
6. Read pictures from assets files
Copy code

/**
* Get the scaled local image
*
*@ param filePath file path
* @return
*/
public static Bitmap readBitmapFromAssetsFile(Context context, String filePath) {
Bitmap image = null;
AssetManager am = context.getResources().getAssets();
try {
InputStream is = am.open(filePath);
image = BitmapFactory.decodeStream(is);
is.close();
} catch (IOException e) {
e.printStackTrace();
}
return image;
}

Copy code
Picture save file:
Copy code

public static void writeBitmapToFile(String filePath, Bitmap b, int quality) {
    try {
        File desFile = new File(filePath);
        FileOutputStream fos = new FileOutputStream(desFile);
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        b.compress(Bitmap.CompressFormat.JPEG, quality, bos);
        bos.flush();
        bos.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Copy code
Picture compression:
Copy code

private static Bitmap compressImage(Bitmap image) {
    if (image == null) {
        return null;
    }
    ByteArrayOutputStream baos = null;
    try {
        baos = new ByteArrayOutputStream();
        image.compress(Bitmap.CompressFormat.JPEG, 100, baos);
        byte[] bytes = baos.toByteArray();
        ByteArrayInputStream isBm = new ByteArrayInputStream(bytes);
        Bitmap bitmap = BitmapFactory.decodeStream(isBm);
        return bitmap;
    } catch (OutOfMemoryError e) {
    } finally {
        try {
            if (baos != null) {
                baos.close();
            }
        } catch (IOException e) {
        }
    }
    return null;
}

Copy code
Picture zooming:
Copy code

/**
 * Generate a picture from scale
 *
 * @param bitmap
 * @param scale  Equivalent scaling value
 * @return
 */
public static Bitmap bitmapScale(Bitmap bitmap, float scale) {
    Matrix matrix = new Matrix();
    matrix.postScale(scale, scale); // Ratio of length and width amplification to reduction
    Bitmap resizeBmp = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
    return resizeBmp;
}

Copy code
Get the image rotation angle:
Copy code

/**
* Rotation Angle in Reading Photo Existence Information
*
*@ param path photo path
*@ return angle
*/
private static int readPictureDegree(String path) {
if (TextUtils.isEmpty(path)) {
return 0;
}
int degree = 0;
try {
ExifInterface exifInterface = new ExifInterface(path);
int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
degree = 90;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
degree = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
degree = 270;
break;
}
} catch (Exception e) {
}
return degree;
}

Copy code
Picture rotation angle:
Copy code

private static Bitmap rotateBitmap(Bitmap b, float rotateDegree) {
    if (b == null) {
        return null;
    }
    Matrix matrix = new Matrix();
    matrix.postRotate(rotateDegree);
    Bitmap rotaBitmap = Bitmap.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(), matrix, true);
    return rotaBitmap;
}

Copy code
Picture to binary:

public byte[] bitmap2Bytes(Bitmap bm) {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
    return baos.toByteArray();
}

Bitmap to Drawable

public static Drawable bitmapToDrawable(Resources resources, Bitmap bm) {
Drawable drawable = new BitmapDrawable(resources, bm);
return drawable;
}

Drawable to Bitmap
Copy code

public static Bitmap drawableToBitmap(Drawable drawable) {
    Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565);
    Canvas canvas = new Canvas(bitmap);
    drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
    drawable.draw(canvas);
    return bitmap;
}

Copy code
Discussion on memory occupancy of Drawable and Bitmap

As you know, Afina and Xutils are familiar with both frameworks. They come from the same person. Xutils is an upgraded version of Afina. The image memory cache in AFina uses Bitmap. Why did Xutils change the object of memory cache to Drawable?

Write a test program:
Copy code

    List<Bitmap> bitmaps = new ArrayList<>();
    start = System.currentTimeMillis();
    for (int i = 0; i < testMaxCount; i++) {
        Bitmap bitmap = BitmapUtils.readBitMap(this, R.mipmap.ic_app_center_banner);
        bitmaps.add(bitmap);
        Log.e(TAG, "BitmapFactory Bitmap--num-->" + i);
    }
    end = System.currentTimeMillis();
    Log.e(TAG, "BitmapFactory Bitmap--time-->" + (end - start));

    List<Drawable> drawables = new ArrayList<>();

    start = System.currentTimeMillis();
    for (int i = 0; i < testMaxCount; i++) {
        Drawable drawable = getResources().getDrawable(R.mipmap.ic_app_center_banner);
        drawables.add(drawable);
        Log.e(TAG, "BitmapFactory Drawable--num-->" + i);
    }
    end = System.currentTimeMillis();
    Log.e(TAG, "BitmapFactory Drawable--time-->" + (end - start));

Copy code

Test data 1000 same picture

Bitmap hangs up when it has 70 pieces of data directly

Drawable Easy 1000 Data Pass

Tests show that Drawable has a large memory footprint advantage over Bitmap. This is also why Drawable is used as a cache object in the memory cache layer of the current mainstream image caching framework.

Summary:

Picture processing will be learned here for the time being and will be supplemented later.

To do our business, when we slack, it means the stop of progress, the stop of progress means being eliminated, can only rush forward, until the day of Phoenix Nirvana!

9. Since the appearance of Fragment, there has been a period of time when I feel that everyone can talk to Fragment about everything, and ask what Fragment can achieve, is it a bit too much?

This blog tries to explain how Fragment is generated, what is Fragment, Fragment life cycle, how to use Fragment statically and dynamically, Fragment backout stack, Fragment transaction, and some special uses of Fragment, such as: what is the use of Fragment without layout? How does Fragment interact with Activity? How does Fragment create dialogs? How Fragment integrates with ActionBar and so on.
1. The Generation and Introduction of Fragment s

Android runs on a variety of devices, including small-screen phones, super-large-screen tablets and even televisions. For the difference of screen size, in many cases, we first develop a set of Apps for mobile phones, then copy a copy, and modify the layout to adapt to the super-large flat screen. Can't an App be adapted to both mobile phones and tablets? Of course, it must be. Fragments appeared to solve such problems. You can think of Fragments as a component of an Activity interface. Even the Activity interface can be made up of completely different Fragments. What's more handsome is that Fragments have their own life cycle and receive and process user events, so you don't have to write a bunch of event handling code for controls in the Activity. More importantly, you can dynamically add, replace and remove a Fragment.
2. Fragment's life cycle

Fragments must exist in dependency and Activity, so the life cycle of Activity will directly affect the life cycle of Fragments. This picture on the official website illustrates the relationship between the two life cycles very well.

You can see that Fragment has several additional lifecycle callback methods than Activity:
onAttach(Activity)
Called when Fragment is associated with Activity.
onCreateView(LayoutInflater, ViewGroup,Bundle)
Create a view of the Fragment
onActivityCreated(Bundle)
Called when Activity's onCreate method returns
onDestoryView()
Corresponding to onCreateView, this Fragment is called when the view is removed
onDetach()
Corresponding to onAttach, it is called when the Fragment and Activity association is cancelled
Note: All other methods except onCreateView, if you override them, you must call the parent class's implementation of the method.
3. Static Use of Fragment

Hey hey, it's finally time to use it.~~

This is the simplest way to use Fragment, which is written directly in Activity's layout file as a common control. Steps:

1. Inherit Fragment and rewrite onCreateView to determine the layout of Fragemnt

2. Declare this Fragment in Activity as if it were a normal View

Here's an example (I use two Fragment s for Activity layout, one for Title layout and one for Content layout):

TitleFragment layout file:

[html] view plain copy

<?xml version="1.0" encoding="utf-8"?>  
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="match_parent"  
    android:layout_height="45dp"  
    android:background="@drawable/title_bar" >  

    <ImageButton  
        android:id="@+id/id_title_left_btn"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:layout_centerVertical="true"  
        android:layout_marginLeft="3dp"  
        android:background="@drawable/showleft_selector" />  

    <TextView  
        android:layout_width="fill_parent"  
        android:layout_height="fill_parent"  
        android:gravity="center"  
        android:text="I'm not Weixin."  
        android:textColor="#fff"  
        android:textSize="20sp"  
        android:textStyle="bold" />  

</RelativeLayout>  

TitleFragment

[java] view plain copy

package com.zhy.zhy_fragments;  

import android.app.Fragment;  
import android.os.Bundle;  
import android.view.LayoutInflater;  
import android.view.View;  
import android.view.View.OnClickListener;  
import android.view.ViewGroup;  
import android.widget.ImageButton;  
import android.widget.Toast;  

public class TitleFragment extends Fragment  
{  

    private ImageButton mLeftMenu;  

    @Override  
    public View onCreateView(LayoutInflater inflater, ViewGroup container,  
            Bundle savedInstanceState)  
    {  
        View view = inflater.inflate(R.layout.fragment_title, container, false);  
        mLeftMenu = (ImageButton) view.findViewById(R.id.id_title_left_btn);  
        mLeftMenu.setOnClickListener(new OnClickListener()  
        {  
            @Override  
            public void onClick(View v)  
            {  
                Toast.makeText(getActivity(),  
                        "i am an ImageButton in TitleFragment ! ",  
                        Toast.LENGTH_SHORT).show();  
            }  
        });  
        return view;  
    }  
}  

Similarly, there are ContentFragment's layout files:

[html] view plain copy

<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    android:orientation="vertical" >  

    <TextView  
        android:layout_width="fill_parent"  
        android:layout_height="fill_parent"  
        android:gravity="center"  
        android:text="Use Fragment Main panel"  
        android:textSize="20sp"  
        android:textStyle="bold" />  

</LinearLayout>  

[java] view plain copy

package com.zhy.zhy_fragments;  

import android.app.Fragment;  
import android.os.Bundle;  
import android.view.LayoutInflater;  
import android.view.View;  
import android.view.ViewGroup;  

public class ContentFragment extends Fragment  
{  

    @Override  
    public View onCreateView(LayoutInflater inflater, ViewGroup container,  
            Bundle savedInstanceState)  
    {  
        return inflater.inflate(R.layout.fragment_content, container, false);  
    }  

}  

MainActivity

[java] view plain copy

package com.zhy.zhy_fragments;  

import android.app.Activity;  
import android.os.Bundle;  
import android.view.Window;  

public class MainActivity extends Activity  
{  

    @Override  
    protected void onCreate(Bundle savedInstanceState)  
    {  
        super.onCreate(savedInstanceState);  
        requestWindowFeature(Window.FEATURE_NO_TITLE);  
        setContentView(R.layout.activity_main);  
    }  

}  

Activity layout file:

[java] view plain copy

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:tools="http://schemas.android.com/tools"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent" >  

    <fragment  
        android:id="@+id/id_fragment_title"  
        android:name="com.zhy.zhy_fragments.TitleFragment"  
        android:layout_width="fill_parent"  
        android:layout_height="45dp" />  

    <fragment  
        android:layout_below="@id/id_fragment_title"  
        android:id="@+id/id_fragment_content"  
        android:name="com.zhy.zhy_fragments.ContentFragment"  
        android:layout_width="fill_parent"  
        android:layout_height="fill_parent" />  

</RelativeLayout>  

Is Fragment declared in Activity's layout file as a normal View, and then all the control's event handling code are processed by their own Fragments, instantly feel that Activity is clean and has code readability, reusability and maintainability? Is it instantly improved? Look at the effect chart below:

4. Dynamic use of Fragment

As demonstrated above, the easiest way to use Fragments is to add, update, and delete Fragments dynamically. ~Here's how to add, update, and delete Fragments dynamically

In order to use Fragment dynamically, let's modify the layout file of Actvity, using a FrameLayout in the middle, and add four buttons below - - Hey Hey Hey is not the button of Wechat -!

[html] view plain copy

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:tools="http://schemas.android.com/tools"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent" >  

    <fragment  
        android:id="@+id/id_fragment_title"  
        android:name="com.zhy.zhy_fragments.TitleFragment"  
        android:layout_width="fill_parent"  
        android:layout_height="45dp" />  

    <include  
        android:id="@+id/id_ly_bottombar"  
        android:layout_width="fill_parent"  
        android:layout_height="55dp"  
        android:layout_alignParentBottom="true"  
        layout="@layout/bottombar" />  

    <FrameLayout  
        android:id="@+id/id_content"  
        android:layout_width="fill_parent"  
        android:layout_height="fill_parent"  
        android:layout_above="@id/id_ly_bottombar"  
        android:layout_below="@id/id_fragment_title" />  

</RelativeLayout>  

The layout of the bottom four buttons will not be pasted, so you will see the effect map.~~

The following main Activity

[java] view plain copy

package com.zhy.zhy_fragments;  

import android.app.Activity;  
import android.app.FragmentManager;  
import android.app.FragmentTransaction;  
import android.os.Bundle;  
import android.view.View;  
import android.view.View.OnClickListener;  
import android.view.Window;  
import android.widget.LinearLayout;  

public class MainActivity extends Activity implements OnClickListener  
{  
    private LinearLayout mTabWeixin;  
    private LinearLayout mTabFriend;  

    private ContentFragment mWeixin;  
    private FriendFragment mFriend;  

    @Override  
    protected void onCreate(Bundle savedInstanceState)  
    {  
        super.onCreate(savedInstanceState);  
        requestWindowFeature(Window.FEATURE_NO_TITLE);  
        setContentView(R.layout.activity_main);  

        // Initialize controls and declare events  
        mTabWeixin = (LinearLayout) findViewById(R.id.tab_bottom_weixin);  
        mTabFriend = (LinearLayout) findViewById(R.id.tab_bottom_friend);  
        mTabWeixin.setOnClickListener(this);  
        mTabFriend.setOnClickListener(this);  

        // Setting the default Fragment  
        setDefaultFragment();  
    }  

    private void setDefaultFragment()  
    {  
        FragmentManager fm = getFragmentManager();  
        FragmentTransaction transaction = fm.beginTransaction();  
        mWeixin = new ContentFragment();  
        transaction.replace(R.id.id_content, mWeixin);  
        transaction.commit();  
    }  

    @Override  
    public void onClick(View v)  
    {  
        FragmentManager fm = getFragmentManager();  
        // Open Fragment transaction  
        FragmentTransaction transaction = fm.beginTransaction();  

        switch (v.getId())  
        {  
        case R.id.tab_bottom_weixin:  
            if (mWeixin == null)  
            {  
                mWeixin = new ContentFragment();  
            }  
            // Control that replaces id_content with the current Fragment layout  
            transaction.replace(R.id.id_content, mWeixin);  
            break;  
        case R.id.tab_bottom_friend:  
            if (mFriend == null)  
            {  
                mFriend = new FriendFragment();  
            }  
            transaction.replace(R.id.id_content, mFriend);  
            break;  
        }  
        // transaction.addToBackStack();  
        // Transaction submission  
        transaction.commit();  
    }  

}  

As you can see, we use Fragment Manager to dynamically load Fragments. Here we use the replace method ~~The next section details the common API s of Fragment Manager.

Note: If you use versions below Android 3.0, you need to introduce v4 packages, then Activity inherits FragmentActivity, and then gets FragmentManager through getSupportFragmentManager. However, the minSdKV ersion and targetSdKV ersion of uses-sdk of Menifest file are all changed to more than 11, so there is no need to introduce v4 package.

There are also two subclasses of Fragment in the middle of the code. As you've seen above, FriendFragment is actually similar:

[java] view plain copy

package com.zhy.zhy_fragments;  

import android.app.Fragment;  
import android.os.Bundle;  
import android.view.LayoutInflater;  
import android.view.View;  
import android.view.ViewGroup;  

public class FriendFragment extends Fragment  
{  

    @Override  
    public View onCreateView(LayoutInflater inflater, ViewGroup container,  
            Bundle savedInstanceState)  
    {  
        return inflater.inflate(R.layout.fragment_friend, container, false);  
    }  

}  

Design sketch:

You can see a very good implementation effect, in fact, this effect has appeared in previous blogs, in the blog: Android project Tab type main interface summary Fragment + TabPage Indicator + ViewPager, interested to see. ps: For the sake of code simplicity, there is no need to add button clicks to change anything. The main function is explained.~~~
5. API commonly used by Fragment family

There are three categories commonly used by Fragment s: fragments, fragments, fragments, fragments, fragments, fragments, fragments, fragments, fragments, fragments and fragments.

android.app.Fragment is mainly used to define Fragment.

Android. app. Fragment Manager is mainly used to operate Fragment in Activity.

android.app.FragmentTransaction guarantees the atomicity of some columns of Fragmentation operations. If you are familiar with the word transaction, you will understand it.~

a. How to obtain FragmentManage:

GetFragment Manager ()// v4, getSupportFragment Manager

b. The main operation is the FragmentTransaction method

FragmentTransaction transaction = fm.benginTransatcion(); // Open a transaction

transaction.add()

Add a Fragment to Activity

transaction.remove()

Remove a Fragment from Activity, and if the removed Fragment is not added to the fallback stack (which will be described in detail later), the Fragment instance will be destroyed.

transaction.replace()

Replacing the current one with another Fragment is actually a combination of remove() and add().~

transaction.hide()

Hide the current Fragment, just to be invisible, not destroyed

transaction.show()

Display previously hidden Fragment s

detach()

view is removed from the UI, unlike remove(), where the status of the fragment is still maintained by the Fragment Manager.

attach()

Reconstruct the view view, attach it to the UI and display it.

transatcion.commit()// commit a transaction

Note: Brothers who use Fragment s often encounter activities with inconsistent states: errors like State loss. The main reason is that the commit method must be invoked before Activity.onSaveInstance().

Above all, it is basically all the way to manipulate Fragment s. When a transaction is opened to commit, it can be added, removed, replaced and so on.

It's worth noting that if you like to use Fragment s, make sure you know which of these methods will destroy views, which will destroy instances, and which is just hidden, so that you can use them better.

For example: I filled in some data in EditText of FragmentA. When switching to FragmentB, hide and show are suitable for you if you want to see data in A. That is to say, you can use hide and show if you want to keep the user's operation panel. Of course, don't make any effort to make a non-null judgment in that new instance.

b. Another example: I don't want to keep user actions, you can use remove(), then add(); or use replace() and remove,add is the same effect.

c, remove and detach are slightly different. Without considering the backout stack, remove destroys the entire Fragment instance, while detach destroys only its view structure, and the instance will not be destroyed. So how to choose between the two? If your current Activity exists all the time, you can use detach first when you don't want to retain user actions.

The above mentioned methods have been introduced and some of the commonly used Fragments have been completed. I believe that after reading them, you will have a clear understanding of the physiological reasons for Fragments and how to use Fragments. Then, according to the API, you can also understand why you thought Fragments had some problems of disorder, which is ultimately due to the lack of a clear understanding of their life cycle.

For space reasons, the rest is left for the next article. In the next article, we will introduce:

1. How to Manage Fragment Return Stack

2. How Fragment Interacts with Activity

3. Best Practices of Fragment Interacting with Activity

4. Use of Fragment s without Views

5. Create a dialog box using Fragment

6. How to integrate with ActionBar, MenuItem, etc.~~

This article will introduce what was mentioned in the previous blog: how to manage the Fragment fallback stack, how Fragment interacts with Activity, the best practices of Fragment interacting with Activity, the use of Fragment without view, how to create dialog boxes using Fragment, how to integrate with ActionBar, MenuItem, etc.~~
1. Managing Fragment Return Stack

Similar to Android, which maintains a task stack for Activity, we can also maintain a fallback stack through Activity to preserve every change in Fragment transactions. If you add the Fragment task to the fallback stack, when the user clicks the fallback button, you will see the last saved Fragment. Once Fragment pops up completely from the backup stack and the user clicks the backoff button again, it exits the current activity.

Look at such an effect:

Click the first button, switch to the second interface, click the second button, switch to the third interface, and then click the Back button to go back in turn. It's not like an Activity jump when I first learned android. Of course, it's definitely not here. Otherwise, I'll kneel. Here is the implementation of Fragment, the user clicks on Back, which is actually the continuous stack of Fragment Back stack.

How to add a Fragment transaction to the fallback stack:

FragmentTransaction.addToBackStack(String)

Here's the code: Obviously there are three Fragment s and one Activity.

Look at Activity's layout file first:

[html] view plain copy

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:tools="http://schemas.android.com/tools"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent" >  

    <FrameLayout  
        android:id="@+id/id_content"  
        android:layout_width="fill_parent"  
        android:layout_height="fill_parent" >  
    </FrameLayout>  

</RelativeLayout>  

Different Fragment s are shown in this FrameLayout.

MainActivity.java

[java] view plain copy

package com.zhy.zhy_fragments;  

import android.app.Activity;  
import android.app.FragmentManager;  
import android.app.FragmentTransaction;  
import android.os.Bundle;  
import android.view.Window;  

public class MainActivity extends Activity  
{  


    @Override  
    protected void onCreate(Bundle savedInstanceState)  
    {  
        super.onCreate(savedInstanceState);  
        requestWindowFeature(Window.FEATURE_NO_TITLE);  
        setContentView(R.layout.activity_main);  

        FragmentManager fm = getFragmentManager();  
        FragmentTransaction tx = fm.beginTransaction();  
        tx.add(R.id.id_content, new FragmentOne(),"ONE");  
        tx.commit();  
    }  

}  

Simply add FragmentOne directly to the FrameLayout in the layout file. Note that FragmentTransaction.addToBackStack(String) is not called here because I don't like to click the Back button to appear on the whiteboard when it is currently displayed. It's the right Back key to exit our Activity.

Here's FragmentOne

[java] view plain copy

package com.zhy.zhy_fragments;  

import android.app.Fragment;  
import android.app.FragmentManager;  
import android.app.FragmentTransaction;  
import android.os.Bundle;  
import android.view.LayoutInflater;  
import android.view.View;  
import android.view.View.OnClickListener;  
import android.view.ViewGroup;  
import android.widget.Button;  

public class FragmentOne extends Fragment implements OnClickListener  
{  

    private Button mBtn;  

    @Override  
    public View onCreateView(LayoutInflater inflater, ViewGroup container,  
            Bundle savedInstanceState)  
    {  
        View view = inflater.inflate(R.layout.fragment_one, container, false);  
        mBtn = (Button) view.findViewById(R.id.id_fragment_one_btn);  
        mBtn.setOnClickListener(this);  
        return view;  
    }  

    @Override  
    public void onClick(View v)  
    {  
        FragmentTwo fTwo = new FragmentTwo();  
        FragmentManager fm = getFragmentManager();  
        FragmentTransaction tx = fm.beginTransaction();  
        tx.replace(R.id.id_content, fTwo, "TWO");  
        tx.addToBackStack(null);  
        tx.commit();  

    }  

}  

When we click on the button in FragmentOne, we use the replace method. If you read the previous blog, you must remember that replace is a combination of remove and add, and if you do not add transactions to the fallback stack, the previous Fragment instance will be destroyed. Obviously, we call tx.addToBackStack(null); add the current transaction to the fallback stack, so the FragmentOne instance will not be destroyed, but the view level will still be destroyed, that is, onDestoryView and onCreateView will be called. The proof is: Look carefully at the effect diagram above, what we entered in the text box before jumping, and get the first interface in the user's Back. Time is gone.

Next, Fragment Two

[java] view plain copy

package com.zhy.zhy_fragments;  

import android.app.Fragment;  
import android.app.FragmentManager;  
import android.app.FragmentTransaction;  
import android.os.Bundle;  
import android.view.LayoutInflater;  
import android.view.View;  
import android.view.View.OnClickListener;  
import android.view.ViewGroup;  
import android.widget.Button;  

public class FragmentTwo extends Fragment implements OnClickListener  
{  

    private Button mBtn ;  
    @Override  
    public View onCreateView(LayoutInflater inflater, ViewGroup container,  
            Bundle savedInstanceState)  
    {  
        View view = inflater.inflate(R.layout.fragment_two, container, false);  
        mBtn = (Button) view.findViewById(R.id.id_fragment_two_btn);  
        mBtn.setOnClickListener(this);  
        return view ;   
    }  
    @Override  
    public void onClick(View v)  
    {  
        FragmentThree fThree = new FragmentThree();  
        FragmentManager fm = getFragmentManager();  
        FragmentTransaction tx = fm.beginTransaction();  
        tx.hide(this);  
        tx.add(R.id.id_content , fThree, "THREE");  
//      tx.replace(R.id.id_content, fThree, "THREE");  
        tx.addToBackStack(null);  
        tx.commit();  
    }  


}  

When we click here, instead of using replace, we first hide the current Fragment, then add an instance of FragmentThree, and finally add the transaction to the fallback stack. The purpose of this is to provide you with a solution: if you don't want the view to be redrawn, please take a closer look at the rendering again. What we filled in in in EditText of FragmentTwo is that the data is still there when the user comes Back.~~~

Finally, FragmentThree is simply Toast:

[java] view plain copy

package com.zhy.zhy_fragments;  

import android.app.Fragment;  
import android.os.Bundle;  
import android.view.LayoutInflater;  
import android.view.View;  
import android.view.View.OnClickListener;  
import android.view.ViewGroup;  
import android.widget.Button;  
import android.widget.Toast;  

public class FragmentThree extends Fragment implements OnClickListener  
{  

    private Button mBtn;  

    @Override  
    public View onCreateView(LayoutInflater inflater, ViewGroup container,  
            Bundle savedInstanceState)  
    {  
        View view = inflater.inflate(R.layout.fragment_three, container, false);  
        mBtn = (Button) view.findViewById(R.id.id_fragment_three_btn);  
        mBtn.setOnClickListener(this);  
        return view;  
    }  

    @Override  
    public void onClick(View v)  
    {  
        Toast.makeText(getActivity(), " i am a btn in Fragment three",  
                Toast.LENGTH_SHORT).show();  
    }  

}  

Well, after the introduction above, you should already know what the Fragment Return Stack is like, and the scenarios of hide, replace and other applications.

Here's a great note: the whole code above does not have any reference value, just to show the fallback stack. After explaining the communication between Fragment and Activity later, the code above will be reconstructed!
2. Fragment and Activity Communication

Because all fragments are dependent on Activity, communication is not complicated, which can be summarized as follows:

a. If you include references to Fragments you manage in your Activity, you can access all Fragments'public methods directly by reference

b. If no reference to Fragment is saved in Activity, then it doesn't matter. Each Fragment has a unique TAG or ID. Any Fragment instance can be obtained through getFragmentManager.findFragmentByTag() or findFragmentById() and then operated on.

c. In Fragment, you can get an instance of the currently bound Activity through getActivity, and then operate on it.

Note: If you need Context in Fragment, you can call getActivity(), and if the Context needs to exist after the Activity is destroyed, use getActivity().getApplicationContext().
3. Best Practices of Fragment and Activity Communication

Considering the reuse of Fragments, the coupling between Fragments and Activities must be reduced, and Fragments should not operate other Fragments directly. After all, Fragments operation should be decided by its manager Activity.

Next, I refactor the click events of FragmentOne and FragmentTwo, and the response of Activity to the click events through two ways of code:

First look at FragmentOne

[java] view plain copy

package com.zhy.zhy_fragments;  

import android.app.Fragment;  
import android.os.Bundle;  
import android.view.LayoutInflater;  
import android.view.View;  
import android.view.View.OnClickListener;  
import android.view.ViewGroup;  
import android.widget.Button;  

public class FragmentOne extends Fragment implements OnClickListener  
{  
    private Button mBtn;  

    /** 
     * Set the callback button clicks 
     * @author zhy 
     * 
     */  
    public interface FOneBtnClickListener  
    {  
        void onFOneBtnClick();  
    }  

    @Override  
    public View onCreateView(LayoutInflater inflater, ViewGroup container,  
            Bundle savedInstanceState)  
    {  
        View view = inflater.inflate(R.layout.fragment_one, container, false);  
        mBtn = (Button) view.findViewById(R.id.id_fragment_one_btn);  
        mBtn.setOnClickListener(this);  
        return view;  
    }  

    /** 
     * Hand it over to the host Activity if it wants to 
     */  
    @Override  
    public void onClick(View v)  
    {  
        if (getActivity() instanceof FOneBtnClickListener)  
        {  
            ((FOneBtnClickListener) getActivity()).onFOneBtnClick();  
        }  
    }  

}  

As you can see, FragmentOne is not coupled with any activity, any activity can be used; and we declare an interface to call back its click event, and the activity that wants to manage its click event can implement this interface. You can see that we first determine in onClick whether the currently bound Activity implements the interface, and if so, call it.

Look again at Fragment Two

[java] view plain copy

package com.zhy.zhy_fragments;  

import android.app.Fragment;  
import android.os.Bundle;  
import android.view.LayoutInflater;  
import android.view.View;  
import android.view.View.OnClickListener;  
import android.view.ViewGroup;  
import android.widget.Button;  

public class FragmentTwo extends Fragment implements OnClickListener  
{  


    private Button mBtn ;  

    private FTwoBtnClickListener fTwoBtnClickListener ;  

    public interface FTwoBtnClickListener  
    {  
        void onFTwoBtnClick();  
    }  
    //Setting up callback interface  
    public void setfTwoBtnClickListener(FTwoBtnClickListener fTwoBtnClickListener)  
    {  
        this.fTwoBtnClickListener = fTwoBtnClickListener;  
    }  
    @Override  
    public View onCreateView(LayoutInflater inflater, ViewGroup container,  
            Bundle savedInstanceState)  
    {  
        View view = inflater.inflate(R.layout.fragment_two, container, false);  
        mBtn = (Button) view.findViewById(R.id.id_fragment_two_btn);  
        mBtn.setOnClickListener(this);  
        return view ;   
    }  
    @Override  
    public void onClick(View v)  
    {  
        if(fTwoBtnClickListener != null)  
        {  
            fTwoBtnClickListener.onFTwoBtnClick();  
        }  
    }  

}  

It's very similar to FragmentOne, but we provide a method like setListener, which means that Activity not only needs to implement the interface, but also must display the call mFTwo.setfTwoBtnClickListener(this).

Finally, look at Activity:

[java] view plain copy

package com.zhy.zhy_fragments;  

import android.app.Activity;  
import android.app.FragmentManager;  
import android.app.FragmentTransaction;  
import android.os.Bundle;  
import android.view.Window;  

import com.zhy.zhy_fragments.FragmentOne.FOneBtnClickListener;  
import com.zhy.zhy_fragments.FragmentTwo.FTwoBtnClickListener;  

public class MainActivity extends Activity implements FOneBtnClickListener,  
        FTwoBtnClickListener  
{  

    private FragmentOne mFOne;  
    private FragmentTwo mFTwo;  
    private FragmentThree mFThree;  

    @Override  
    protected void onCreate(Bundle savedInstanceState)  
    {  
        super.onCreate(savedInstanceState);  
        requestWindowFeature(Window.FEATURE_NO_TITLE);  
        setContentView(R.layout.activity_main);  

        mFOne = new FragmentOne();  
        FragmentManager fm = getFragmentManager();  
        FragmentTransaction tx = fm.beginTransaction();  
        tx.add(R.id.id_content, mFOne, "ONE");  
        tx.commit();  
    }  

    /** 
     * FragmentOne Callback when the button is clicked 
     */  
    @Override  
    public void onFOneBtnClick()  
    {  

        if (mFTwo == null)  
        {  
            mFTwo = new FragmentTwo();  
            mFTwo.setfTwoBtnClickListener(this);  
        }  
        FragmentManager fm = getFragmentManager();  
        FragmentTransaction tx = fm.beginTransaction();  
        tx.replace(R.id.id_content, mFTwo, "TWO");  
        tx.addToBackStack(null);  
        tx.commit();  
    }  

    /** 
     * FragmentTwo Callback when the button is clicked 
     */  
    @Override  
    public void onFTwoBtnClick()  
    {  
        if (mFThree == null)  
        {  
            mFThree = new FragmentThree();  

        }  
        FragmentManager fm = getFragmentManager();  
        FragmentTransaction tx = fm.beginTransaction();  
        tx.hide(mFTwo);  
        tx.add(R.id.id_content, mFThree, "THREE");  
        // tx.replace(R.id.id_content, fThree, "THREE");  
        tx.addToBackStack(null);  
        tx.commit();  
    }  

}  

The end of code refactoring is exactly the same as the beginning. The above two modes of communication are worth recommending. Choose any one you like. Here's another point: Although Fragments and Activities can do anything through getActivity with findFragmentByTag or findFragmentById, or even operate other Fragments in Fragments, there's no special reason to be absolutely undesirable. Activity plays a bus-like role between Fragments, and it should determine how Fragments operate. In addition, although Fragment cannot respond to Intent opening, Activity can accept Intent and then decide which Fragment to display according to its parameters.

4. How to handle runtime configuration changes

The most common change in runtime configuration is screen rotation. If you don't know how to handle screen changes, you can refer to: The best solution for Android screen rotation to handle AsyncTask and rogressDialog

Here's a note: Many people think it's OK to force the direction of the screen, but one thing is that when your application is in the background (e.g. when the user clicks on home) for a long time without returning, your application will be restarted. For example, if you take the example above and you go back to the FragmentThree interface, you will find that when you open it again through home, the FragmentThree and FragmentOne are superimposed on it. That's because your Activeness restart and you draw a FragmentOne on the original FragmentThree.

Okay, let's look at a piece of code:

Activity:

[java] view plain copy

package com.zhy.zhy_fragments;  

import android.app.Activity;  
import android.app.FragmentManager;  
import android.app.FragmentTransaction;  
import android.os.Bundle;  
import android.view.Window;  

public class MainActivity extends Activity  

{  
    private FragmentOne mFOne;  

    @Override  
    protected void onCreate(Bundle savedInstanceState)  
    {  
        super.onCreate(savedInstanceState);  
        requestWindowFeature(Window.FEATURE_NO_TITLE);  
        setContentView(R.layout.activity_main);  

        mFOne = new FragmentOne();  
        FragmentManager fm = getFragmentManager();  
        FragmentTransaction tx = fm.beginTransaction();  
        tx.add(R.id.id_content, mFOne, "ONE");  
        tx.commit();  

    }  

}  

Fragment

[java] view plain copy

package com.zhy.zhy_fragments;  

import android.app.Fragment;  
import android.os.Bundle;  
import android.util.Log;  
import android.view.LayoutInflater;  
import android.view.View;  
import android.view.ViewGroup;  

public class FragmentOne extends Fragment  
{  
    private static final String TAG = "FragmentOne";  

    @Override  
    public View onCreateView(LayoutInflater inflater, ViewGroup container,  
            Bundle savedInstanceState)  
    {  
        Log.e(TAG, "onCreateView");  
        View view = inflater.inflate(R.layout.fragment_one, container, false);  
        return view;  
    }  

    @Override  
    public void onCreate(Bundle savedInstanceState)  
    {  
        // TODO Auto-generated method stub  
        super.onCreate(savedInstanceState);  

        Log.e(TAG, "onCreate");  
    }  

    @Override  
    public void onDestroyView()  
    {  
        // TODO Auto-generated method stub  
        super.onDestroyView();  
        Log.e(TAG, "onDestroyView");  
    }  

    @Override  
    public void onDestroy()  
    {  
        // TODO Auto-generated method stub  
        super.onDestroy();  
        Log.e(TAG, "onDestroy");  
    }  

}  

Very simple code, when you run, constantly rotating the screen, you will find that every time you rotate the screen, there is an additional instance of FragmentOne on the screen, and the background log will print out many sets of life cycle callbacks.

Similar:

[html] view plain copy

07-20 08:18:46.651: E/FragmentOne(1633): onCreate  
07-20 08:18:46.651: E/FragmentOne(1633): onCreate  
07-20 08:18:46.651: E/FragmentOne(1633): onCreate  
07-20 08:18:46.681: E/FragmentOne(1633): onCreateView  
07-20 08:18:46.831: E/FragmentOne(1633): onCreateView  
07-20 08:18:46.891: E/FragmentOne(1633): onCreateView  

This is why, because when the screen rotates, Activity restarts, and Fragments in the default Active are recreated with Activity; this causes the existing Fragments to reboot when the screen rotates, and then a new Fragment is instantiated again when the onCreate of Activity is executed, which is why this happens.

So how to solve it?

Actually, by checking the parameter Bundle saved InstanceState of onCreate, we can judge whether the recreation of Activity occurs at present:

The default saved Instance State stores some data, including instances of Fragment: you can see by printing:

[java] view plain copy

07-20 08:23:12.952: E/FragmentOne(1782): Bundle[{android:fragments=android.app.FragmentManagerState@40d0b7b8, android:viewHierarchyState=Bundle[{android:focusedViewId=2131230721, android:views=android.util.SparseArray@40d0af68}]}]  

So, let's simply change the code to create a Fragment instance only when saved InstanceState==null:

[java] view plain copy

package com.zhy.zhy_fragments;  

import android.app.Activity;  
import android.app.FragmentManager;  
import android.app.FragmentTransaction;  
import android.os.Bundle;  
import android.util.Log;  
import android.view.Window;  

public class MainActivity extends Activity  

{  
    private static final String TAG = "FragmentOne";  
    private FragmentOne mFOne;  

    @Override  
    protected void onCreate(Bundle savedInstanceState)  
    {  
        super.onCreate(savedInstanceState);  
        requestWindowFeature(Window.FEATURE_NO_TITLE);  
        setContentView(R.layout.activity_main);  

        Log.e(TAG, savedInstanceState+"");  

        if(savedInstanceState == null)  
        {  
            mFOne = new FragmentOne();  
            FragmentManager fm = getFragmentManager();  
            FragmentTransaction tx = fm.beginTransaction();  
            tx.add(R.id.id_content, mFOne, "ONE");  
            tx.commit();  
        }  



    }  

}  

Now, no matter how many rotations are made, there will only be one Fragment instance in Activity.

Now there is still a problem, that is, when the Fragment is redrawn, how to maintain the original data?

Similar to Activeness, Fragment also has an onSave InstanceState method, in which data is saved and then restored in onCreate or onCreateView or on Activity Created.

Because of space, test code will not be pasted.
5. Integration of Fragmeny with ActionBar and MenuItem

Fragment can add its own MenuItem to ActionBar of Activity or to an optional menu.

a. Call setHasOptionsMenu(true) in Fragment's onCreate.

b. Then implement onCreateOptionsMenu in the Fragment subclass

c. If you want to handle MenuItem clicks in Fragment, you can also implement onOptions Item Selected; of course, Activity can also directly handle the MenuItem click events.

Code:

Fragment

[java] view plain copy

package com.zhy.zhy_fragments;  

import android.app.Fragment;  
import android.os.Bundle;  
import android.view.LayoutInflater;  
import android.view.Menu;  
import android.view.MenuInflater;  
import android.view.MenuItem;  
import android.view.View;  
import android.view.ViewGroup;  
import android.widget.Toast;  

public class FragmentOne extends Fragment  
{  

    @Override  
    public void onCreate(Bundle savedInstanceState)  
    {  
        super.onCreate(savedInstanceState);  
        setHasOptionsMenu(true);  
    }  

    @Override  
    public View onCreateView(LayoutInflater inflater, ViewGroup container,  
            Bundle savedInstanceState)  
    {  
        View view = inflater.inflate(R.layout.fragment_one, container, false);  
        return view;  
    }  

    @Override  
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)  
    {  
        inflater.inflate(R.menu.fragment_menu, menu);  
    }  

    @Override  
    public boolean onOptionsItemSelected(MenuItem item)  
    {  
        switch (item.getItemId())  
        {  
        case R.id.id_menu_fra_test:  
            Toast.makeText(getActivity(), "FragmentMenuItem1", Toast.LENGTH_SHORT).show();  
            break;  
        }  
        return true;  
    }  

}  

Activity

[java] view plain copy

package com.zhy.zhy_fragments;  

import android.app.Activity;  
import android.app.FragmentManager;  
import android.app.FragmentTransaction;  
import android.os.Bundle;  
import android.util.Log;  
import android.view.Menu;  
import android.view.MenuItem;  
import android.view.Window;  
import android.widget.Toast;  

public class MainActivity extends Activity  

{  
    private static final String TAG = "FragmentOne";  
    private FragmentOne mFOne;  

    @Override  
    protected void onCreate(Bundle savedInstanceState)  
    {  
        super.onCreate(savedInstanceState);  
        requestWindowFeature(Window.FEATURE_NO_TITLE);  
        setContentView(R.layout.activity_main);  

        Log.e(TAG, savedInstanceState + "");  

        if (savedInstanceState == null)  
        {  
            mFOne = new FragmentOne();  
            FragmentManager fm = getFragmentManager();  
            FragmentTransaction tx = fm.beginTransaction();  
            tx.add(R.id.id_content, mFOne, "ONE");  
            tx.commit();  
        }  

    }  

    @Override  
    public boolean onCreateOptionsMenu(Menu menu)  
    {  
        super.onCreateOptionsMenu(menu);  
        getMenuInflater().inflate(R.menu.main, menu);  
        return true;  
    }  

    @Override  
    public boolean onOptionsItemSelected(MenuItem item)  
    {  
        switch (item.getItemId())  
        {  
        case R.id.action_settings:  
            Toast.makeText(this, "setting", Toast.LENGTH_SHORT).show();  
            return true;  
        default:  
            //If you want Fragment to handle MenuItem click events by itself, don't forget to call super.xxx  
            return super.onOptionsItemSelected(item);  
        }  
    }  

}  

Design sketch:

Well, as you can see, Fragment can add MenuItem or handle clicks by itself.~~~
6. The Role of Fragment s without Layout

Fragment s without layout files are actually intended to be saved. When Activity restarts, a large amount of data is saved.

Refer to Blog: The best way to rotate Android screen to handle AsyncTask and rogressDialog

7. Create dialogs using Fragment s

This is the way Google recommends, and I've written a separate blog introduction. See: Android Official Recommendation: Dialog Fragment Creates Dialog Box

Okay, finally, I've linked Fragments together. The above basically includes all the uses of Fragments. ~I believe that if you can read them, you will have a lot to gain.~

If you have any questions, please leave a message.~~~

At the end of the two articles, I believe you have a certain understanding of Fragment, so what are the best practices in the project? Step away: Android Fragment s What You Should Know

10. The difference between fragments and framlayouts:
FrameLayout and Fragment tags are used to place Fragments. The difference is that Fragment tags can only set fixed Fragments, while Fragments can be replaced by Fragment Manager in FrameLayout.

11. Customize View1:
For reprinting, please indicate the source: http://blog.csdn.NET/lmj623565791/article/details/24252901

Many Android entry-level apes may be scared of Android custom View, but this is the only way for a master to advance. All of them are ready to spend some time on the custom View and write more articles. First summarize the steps of customizing View:

1. Properties of custom View

2. Obtain our custom attributes in View's construction method

[3. Rewrite onMesure]

4. Rewrite onDraw

I marked 3 with [], so 3 is not necessarily necessary, of course, in most cases it still needs to be rewritten.

1. Customize the attributes of View. First, create an attrs.xml under res/values / to define our attributes and declare our entire style.

[html] view plain copy

<?xml version="1.0" encoding="utf-8"?>  
<resources>  

    <attr name="titleText" format="string" />  
    <attr name="titleTextColor" format="color" />  
    <attr name="titleTextSize" format="dimension" />  

    <declare-styleable name="CustomTitleView">  
        <attr name="titleText" />  
        <attr name="titleTextColor" />  
        <attr name="titleTextSize" />  
    </declare-styleable>  

</resources>  

We define three attributes: font, font color and font size. Form is the value type of the attribute.

There are: string,color,demension,integer,enum,reference,float,boolean,fraction,flag; google is the one that is not clear.

Then declare our custom View in the layout

[objc] view plain copy

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:tools="http://schemas.android.com/tools"  
    xmlns:custom="http://schemas.android.com/apk/res/com.example.customview01"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent" >  

    <com.example.customview01.view.CustomTitleView  
        android:layout_width="200dp"  
        android:layout_height="100dp"  
        custom:titleText="3712"  
        custom:titleTextColor="#ff0000"  
        custom:titleTextSize="40sp" />  

</RelativeLayout>  

Make sure to introduce xmlns:custom= "http://schemas.android.com/apk/res/com.example.customview01" into our namespace. The later package path refers to the package of the project.

2. Obtain our custom style in View's construction method

[java] view plain copy

/** 
     * text 
     */  
    private String mTitleText;  
    /** 
     * Color of Text 
     */  
    private int mTitleTextColor;  
    /** 
     * Text size 
     */  
    private int mTitleTextSize;  

    /** 
     * Controlling the range of text rendering during rendering 
     */  
    private Rect mBound;  
    private Paint mPaint;  

    public CustomTitleView(Context context, AttributeSet attrs)  
    {  
        this(context, attrs, 0);  
    }  

    public CustomTitleView(Context context)  
    {  
        this(context, null);  
    }  

    /** 
     * Get my custom style attributes 
     *  
     * @param context 
     * @param attrs 
     * @param defStyle 
     */  
    public CustomTitleView(Context context, AttributeSet attrs, int defStyle)  
    {  
        super(context, attrs, defStyle);  
        /** 
         * Get the custom style attributes we defined 
         */  
        TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomTitleView, defStyle, 0);  
        int n = a.getIndexCount();  
        for (int i = 0; i < n; i++)  
        {  
            int attr = a.getIndex(i);  
            switch (attr)  
            {  
            case R.styleable.CustomTitleView_titleText:  
                mTitleText = a.getString(attr);  
                break;  
            case R.styleable.CustomTitleView_titleTextColor:  
                // The default color is set to black  
                mTitleTextColor = a.getColor(attr, Color.BLACK);  
                break;  
            case R.styleable.CustomTitleView_titleTextSize:  
                // The default setting is 16sp, and TypeValue can also convert SP to px  
                mTitleTextSize = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(  
                        TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics()));  
                break;  

            }  

        }  
        a.recycle();  

        /** 
         * Get the width and height of the rendered text 
         */  
        mPaint = new Paint();  
        mPaint.setTextSize(mTitleTextSize);  
        // mPaint.setColor(mTitleTextColor);  
        mBound = new Rect();  
        mPaint.getTextBounds(mTitleText, 0, mTitleText.length(), mBound);  

    }  

We rewrote three constructors. The default layout file calls the constructor of two parameters. So remember to let all constructors call the constructor of our three parameters. We get custom attributes in the construction of three parameters.

3. We rewrite onDraw, which is provided by onMesure calling system:

[java] view plain copy

@Override  
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)  
    {  
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);  
    }  

    @Override  
    protected void onDraw(Canvas canvas)  
    {  
        mPaint.setColor(Color.YELLOW);  
        canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint);  

        mPaint.setColor(mTitleTextColor);  
        canvas.drawText(mTitleText, getWidth() / 2 - mBound.width() / 2, getHeight() / 2 + mBound.height() / 2, mPaint);  
    }  

The effect at this time is:

Do you think it's good? You've basically implemented a custom View. But at this point, if we write the width and height of the layout file as wrap_content, we will find that the effect is not what we expected:

The height and width that the system helps us to measure are both MATCH_PARNET. When we set the clear width and height, the result that the system helps us to measure is the result that we set. When we set it to WRAP_CONTENT, or the result that the MATCH_PARENT system helps us to measure is the length of MATCH_PARENT.

So when WRAP_CONTENT is set up, we need to measure it ourselves, that is, rewrite the onMesure method":

Before rewriting, learn about the specMode of MeasureSpec. There are three types:

EXACTLY: Usually set a clear value or MATCH_PARENT

AT_MOST: Represents that the sublayout is limited to a maximum, usually WARP_CONTENT

UNSPECIFIED: Represents how big the sub-layout is and is rarely used

Here is our rewrite of onMeasure code:

[java] view plain copy

@Override  
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)  
{  
    int widthMode = MeasureSpec.getMode(widthMeasureSpec);  
    int widthSize = MeasureSpec.getSize(widthMeasureSpec);  
    int heightMode = MeasureSpec.getMode(heightMeasureSpec);  
    int heightSize = MeasureSpec.getSize(heightMeasureSpec);  
    int width;  
    int height ;  
    if (widthMode == MeasureSpec.EXACTLY)  
    {  
        width = widthSize;  
    } else  
    {  
        mPaint.setTextSize(mTitleTextSize);  
        mPaint.getTextBounds(mTitle, 0, mTitle.length(), mBounds);  
        float textWidth = mBounds.width();  
        int desired = (int) (getPaddingLeft() + textWidth + getPaddingRight());  
        width = desired;  
    }  

    if (heightMode == MeasureSpec.EXACTLY)  
    {  
        height = heightSize;  
    } else  
    {  
        mPaint.setTextSize(mTitleTextSize);  
        mPaint.getTextBounds(mTitle, 0, mTitle.length(), mBounds);  
        float textHeight = mBounds.height();  
        int desired = (int) (getPaddingTop() + textHeight + getPaddingBottom());  
        height = desired;  
    }  



    setMeasuredDimension(width, height);  
}  

Now let's modify the layout file:

[html] view plain copy

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:tools="http://schemas.android.com/tools"  
    xmlns:custom="http://schemas.android.com/apk/res/com.example.customview01"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent" >  

    <com.example.customview01.view.CustomTitleView  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        custom:titleText="3712"  
        android:padding="10dp"  
        custom:titleTextColor="#ff0000"  
        android:layout_centerInParent="true"  
        custom:titleTextSize="40sp" />  

</RelativeLayout>  

Now the effect is:

Completely compounding our expectations, now we can set the height and width arbitrarily, and basically meet our needs.

Of course, in this way, our custom View has no advantage over TextView, so we feel that adding an event to our custom View:

Add:

[java] view plain copy

this.setOnClickListener(new OnClickListener()  
        {  

            @Override  
            public void onClick(View v)  
            {  
                mTitleText = randomText();  
                postInvalidate();  
            }  

        });  

[java] view plain copy

private String randomText()  
    {  
        Random random = new Random();  
        Set<Integer> set = new HashSet<Integer>();  
        while (set.size() < 4)  
        {  
            int randomInt = random.nextInt(10);  
            set.add(randomInt);  
        }  
        StringBuffer sb = new StringBuffer();  
        for (Integer i : set)  
        {  
            sb.append("" + i);  
        }  

        return sb.toString();  
    }  

Next run:

We add a click event, each time it randomly generates a 4-bit random number. Interested can add a little noise in onDraw, and then rewrite it to a verification code. Does it feel good?
Custom View2:
For reprinting, please indicate the source: http://blog.csdn.NET/lmj623565791/article/details/24300125

Continue with the customized View tour. An example of the basis of customized View, Android Custom View (1), was introduced earlier. If you still don't know about customized View, you can take a look at it. Today I'm going to give you a slightly more complicated example.

Custom View displays a picture. The text description of the picture is included below. It's similar to what the photo describes. But it's not important. It's mainly about learning the usage of Custom View.

Do you remember the four steps in the last article?

1. Properties of custom View
2. Obtain our custom attributes in View's construction method
[3. Rewrite onMesure]
4. Rewrite onDraw

Directly cut into the main topic:

1. At res/values/attr.xml

[html] view plain copy

<?xml version="1.0" encoding="utf-8"?>  
<resources>  

    <attr name="titleText" format="string" />  
    <attr name="titleTextSize" format="dimension" />  
    <attr name="titleTextColor" format="color" />  
    <attr name="image" format="reference" />  
    <attr name="imageScaleType">  
        <enum name="fillXY" value="0" />  
        <enum name="center" value="1" />  
    </attr>  

    <declare-styleable name="CustomImageView">  
        <attr name="titleText" />  
        <attr name="titleTextSize" />  
        <attr name="titleTextColor" />  
        <attr name="image" />  
        <attr name="imageScaleType" />  
    </declare-styleable>  

</resources>  

2. Get our custom attributes in the construction:

[java] view plain copy

/** 
     * Initialize custom types that are specific to 
     *  
     * @param context 
     * @param attrs 
     * @param defStyle 
     */  
    public CustomImageView(Context context, AttributeSet attrs, int defStyle)  
    {  
        super(context, attrs, defStyle);  

        TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomImageView, defStyle, 0);  

        int n = a.getIndexCount();  

        for (int i = 0; i < n; i++)  
        {  
            int attr = a.getIndex(i);  

            switch (attr)  
            {  
            case R.styleable.CustomImageView_image:  
                mImage = BitmapFactory.decodeResource(getResources(), a.getResourceId(attr, 0));  
                break;  
            case R.styleable.CustomImageView_imageScaleType:  
                mImageScale = a.getInt(attr, 0);  
                break;  
            case R.styleable.CustomImageView_titleText:  
                mTitle = a.getString(attr);  
                break;  
            case R.styleable.CustomImageView_titleTextColor:  
                mTextColor = a.getColor(attr, Color.BLACK);  
                break;  
            case R.styleable.CustomImageView_titleTextSize:  
                mTextSize = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,  
                        16, getResources().getDisplayMetrics()));  
                break;  

            }  
        }  
        a.recycle();  
        rect = new Rect();  
        mPaint = new Paint();  
        mTextBound = new Rect();  
        mPaint.setTextSize(mTextSize);  
        // Calculated the range of font descriptions needed.  
        mPaint.getTextBounds(mTitle, 0, mTitle.length(), mTextBound);  

    }  

3. Rewrite onMeasure

[java] view plain copy

@Override  
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)  
{  
    // super.onMeasure(widthMeasureSpec, heightMeasureSpec);  

    /** 
     * Set width 
     */  
    int specMode = MeasureSpec.getMode(widthMeasureSpec);  
    int specSize = MeasureSpec.getSize(widthMeasureSpec);  

    if (specMode == MeasureSpec.EXACTLY)// match_parent , accurate  
    {  
        Log.e("xxx", "EXACTLY");  
        mWidth = specSize;  
    } else  
    {  
        // Width determined by pictures  
        int desireByImg = getPaddingLeft() + getPaddingRight() + mImage.getWidth();  
        // Width determined by font size  
        int desireByTitle = getPaddingLeft() + getPaddingRight() + mTextBound.width();  

        if (specMode == MeasureSpec.AT_MOST)// wrap_content  
        {  
            int desire = Math.max(desireByImg, desireByTitle);  
            mWidth = Math.min(desire, specSize);  
            Log.e("xxx", "AT_MOST");  
        }  
    }  

    /*** 
     * Set height 
     */  

    specMode = MeasureSpec.getMode(heightMeasureSpec);  
    specSize = MeasureSpec.getSize(heightMeasureSpec);  
    if (specMode == MeasureSpec.EXACTLY)// match_parent , accurate  
    {  
        mHeight = specSize;  
    } else  
    {  
        int desire = getPaddingTop() + getPaddingBottom() + mImage.getHeight() + mTextBound.height();  
        if (specMode == MeasureSpec.AT_MOST)// wrap_content  
        {  
            mHeight = Math.min(desire, specSize);  
        }  
    }  
    setMeasuredDimension(mWidth, mHeight);  

}  

4. Rewrite onDraw

[java] view plain copy

@Override  
    protected void onDraw(Canvas canvas)  
    {  
        // super.onDraw(canvas);  
        /** 
         * Frame 
         */  
        mPaint.setStrokeWidth(4);  
        mPaint.setStyle(Paint.Style.STROKE);  
        mPaint.setColor(Color.CYAN);  
        canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint);  

        rect.left = getPaddingLeft();  
        rect.right = mWidth - getPaddingRight();  
        rect.top = getPaddingTop();  
        rect.bottom = mHeight - getPaddingBottom();  

        mPaint.setColor(mTextColor);  
        mPaint.setStyle(Style.FILL);  
        /** 
         * The width of the current setting is less than the required width of the font. Change the font to xxx. 
         */  
        if (mTextBound.width() > mWidth)  
        {  
            TextPaint paint = new TextPaint(mPaint);  
            String msg = TextUtils.ellipsize(mTitle, paint, (float) mWidth - getPaddingLeft() - getPaddingRight(),  
                    TextUtils.TruncateAt.END).toString();  
            canvas.drawText(msg, getPaddingLeft(), mHeight - getPaddingBottom(), mPaint);  

        } else  
        {  
            //Normally, center the font  
            canvas.drawText(mTitle, mWidth / 2 - mTextBound.width() * 1.0f / 2, mHeight - getPaddingBottom(), mPaint);  
        }  

        //Quick Unuse  
        rect.bottom -= mTextBound.height();  

        if (mImageScale == IMAGE_SCALE_FITXY)  
        {  
            canvas.drawBitmap(mImage, null, rect, mPaint);  
        } else  
        {  
            //Calculate the middle rectangular range  
            rect.left = mWidth / 2 - mImage.getWidth() / 2;  
            rect.right = mWidth / 2 + mImage.getWidth() / 2;  
            rect.top = (mHeight - mTextBound.height()) / 2 - mImage.getHeight() / 2;  
            rect.bottom = (mHeight - mTextBound.height()) / 2 + mImage.getHeight() / 2;  

            canvas.drawBitmap(mImage, null, rect, mPaint);  
        }  

    }  

Code, combined with comments and the use of the first View, should be able to understand, not understand the message. Here we introduce our custom View:

[html] view plain copy

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:tools="http://schemas.android.com/tools"  
    xmlns:zhy="http://schemas.android.com/apk/res/com.zhy.customview02"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    android:orientation="vertical" >  

    <com.zhy.customview02.view.CustomImageView  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:layout_margin="10dp"  
        android:padding="10dp"  
        zhy:image="@drawable/ic_launcher"  
        zhy:imageScaleType="center"  
        zhy:titleText="hello andorid ! "  
        zhy:titleTextColor="#ff0000"  
        zhy:titleTextSize="30sp" />  

    <com.zhy.customview02.view.CustomImageView  
        android:layout_width="100dp"  
        android:layout_height="wrap_content"  
        android:layout_margin="10dp"  
        android:padding="10dp"  
        zhy:image="@drawable/ic_launcher"  
        zhy:imageScaleType="center"  
        zhy:titleText="helloworldwelcome"  
        zhy:titleTextColor="#00ff00"  
        zhy:titleTextSize="20sp" />  

    <com.zhy.customview02.view.CustomImageView  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:layout_margin="10dp"  
        android:padding="10dp"  
        zhy:image="@drawable/lmj"  
        zhy:imageScaleType="center"  
        zhy:titleText="Younger sister~"  
        zhy:titleTextColor="#ff0000"  
        zhy:titleTextSize="12sp" />  

</LinearLayout>  

I intentionally let the display appear in 3 cases:

1. Font width is larger than picture, and View width is set to wrap_content

2. View width is set to an exact value, and font length is greater than this width.

3. The width of the picture is larger than that of the font, and the View width is set to wrap_content.

11.IO
1. What is IO

  I/O operations in Java mainly refer to the use of Java for input and output operations. All I/O mechanisms in Java are based on data streams for input and output, which represent the flow sequence of character or byte data. Java's I/O stream provides a standard way to read and write data. Any object representing a data source in Java provides a way to read and write its data as a data stream.  

  Java.io is the main software package for most data stream-oriented input/output classes. In addition, Java also supports block transport, and block IO is used in the core library java.nio.

The advantage of streaming IO is its simplicity, but its disadvantage is its low efficiency. Block IO is efficient, but its programming is complex.
Java IO model:
Java's IO model is excellent in design. It uses Decorator mode and divides Stream by function. You can assemble these Stream dynamically to get the function you need. For example, if you need a buffered file input stream, you should combine FileInputStream with Buffered InputStream.

2. Basic concepts of data flow

    Data flow is a collection of continuous data, just like water flow in a pipe, which supplies water bit by bit at one end of the pipe, while a continuous flow is seen at the other end of the pipe. The data writing program can write data to the data stream pipeline one by one, which will form a long data stream in sequence. For the data reader, it can not see the segmentation of the data stream when it is written. Every time, it can read any length of data, but only after reading the previous data, then reading the later data. Whether the data is written multiple times or as a whole at a time, the effect of reading is exactly the same. 

  "Stream is the source or destination of data stored on disk or other peripheral devices."

There are three ways to store data on a computer. One is external memory, the other is memory, and the other is caching. For example, the hard disk, disk, U disk on the computer are all external memory, there are memory bars on the computer, the cache is in the CPU. The storage capacity of external memory is the largest, followed by memory, and finally caching, but the reading of external data is the slowest, followed by memory, and caching is the fastest. Here is a summary of reading data from memory to memory and writing data from memory to memory. For the understanding of memory and memory, we can simply understand as a container, that is, external memory is a container, and memory is another container. So how to read the data stored in the outer storage container into the memory container and how to store the data in the memory container into the outer storage?

 In Java class libraries, the content of IO is huge, because it covers a wide range of areas:

     Standard input and output, file operation, data flow on the network, string flow, object flow, zip file flow and so on. In java, the input and output are abstracted as streams, just like water pipes, connecting two containers. Reading data out of memory is called input stream, and writing data out of memory is called output stream.

Stream is a very vivid concept. When a program needs to read data, it opens a stream to the data source, which can be file, memory, or network connection. Similarly, when a program needs to write data, it opens a flow to its destination.

  The basic concepts summarized are as follows:

1) Data stream:

An ordered sequence of bytes with starting and ending points. Including input and output streams.

2) Input Stream:

  The program reads the data source from the input stream. Data sources include the outside world (keyboard, file, network etc.). That is, the communication channel that reads the data source into the program

3) Output stream:
The program writes data to the output stream. Export data from programs to the outside world (display, printer, file, network, etc.) Communication channel.

The purpose of adopting data stream is to make the output and input independent of the device.

Input Stream doesn't care what device the data source comes from (keyboard, file, network)
Output Stream does not care what device the data is intended for (keyboard, file, network)
4 Data stream classification:
The data in the stream sequence can be either raw binary data without processing or specific data in a certain format after encoding. So there are two streams in Java:
1) Byte stream: The smallest data unit in the data stream is the byte.
2) Character Stream: The smallest data unit in the data stream is the character, and the character in Java is Unicode encoding, one character occupies two bytes.

  1. Standard I/O

    Java programs can exchange short information with the outside world through command line parameters. At the same time, they also specify the way to exchange information with standard input and output devices, such as keyboards and monitors. The information can be exchanged with the outside world in any form of data through files.

  2. Command line parameters

[java] view plain copy
print?

public class TestArgs {  
    public static void main(String[] args) {  
        for (int i = 0; i < args.length; i++) {  
            System.out.println("args[" + i + "] is <" + args[i] + ">");  
        }  
    }  
}  

Running commands: java Java C VB

Operation results:

args[0] is

args[1] is

args[2] is

  1. Standard Input, Output Data Flow

Standard data stream of Java system: java.lang.System:

[java] view plain copy
print?

java.lang.System   
public final class System  extends Object{   
   static  PrintStream  err;//Standard error stream (output)  
   static  InputStream  in;//Standard input (keyboard input stream)  
   static  PrintStream  out;//Standard Output Stream (Display Output Stream)  
}  

Be careful:
(1) The System class cannot create objects, but can only use its three static members directly.
(2) Whenever the main method is executed, the above three objects are automatically generated.

1) Standard Output Stream System.

System.out outputs data to standard output devices with the data type PrintStream. Method:

  Void print (parameter)
  Void println (parameter)

2) Standard input stream System.in

System.in Read standard input device data (get data from standard input, usually keyboard), and the data type is InputStream. Method:

    int read()  //Return ASCII code. If the return value is=-1, no byte reading is completed.
     int read(byte[] b)//The number of bytes read in is the return value from reading in multiple bytes to buffer b

For example:
[java] view plain copy
print?

import java.io.*;  
public class StandardInputOutput {  
    public static void main(String args[]) {  
        int b;  
        try {  
            System.out.println("please Input:");  
            while ((b = System.in.read()) != -1) {  
                System.out.print((char) b);  
            }  
        } catch (IOException e) {  
            System.out.println(e.toString());  
        }  
    }  
}  

Waiting for keyboard input, what keyboard input, print out what:

3) Standard error stream

System.err output standard error with data type PrintStream. Refer to the API for detailed instructions.

Standard output calls println method to output parameters and wrap lines through System.out, while print method outputs parameters without wrapping lines. Println or print methods can output basic data types by overloading, including boolean, char, int, long, float and double. At the same time, the method of output parameter type char [], String and Object is also overloaded. The print (Object) and println (Object) methods call the toString method of the parameter Object at run time.

[java] view plain copy
print?

import java.io.BufferedReader;  
import java.io.IOException;  
import java.io.InputStreamReader;  

public class StandardInputOutput {  
    public static void main(String args[]) {  
        String s;  
        // Create a buffer reader to read data line by line from the keyboard  
        InputStreamReader ir = new InputStreamReader(System.in);  
        BufferedReader in = new BufferedReader(ir);  
        System.out.println("Unix system: ctrl-d or ctrl-c Sign out"  
                + "\nWindows system: ctrl-z Sign out");  
        try {  
            // Read a line of data and output it to the monitor  
            s = in.readLine();  
            // If an I/O error occurs while the readLine() method is running, an IOException exception will be thrown.  
            while (s != null) {  
                System.out.println("Read: " + s);  
                s = in.readLine();  
            }  
            // Close Buffer Reader  
            in.close();  
        } catch (IOException e) { // Catch any IO exceptions.  
            e.printStackTrace();  
        }  
    }  
}  

4.java.IO Hierarchical Architecture

 Five classes and one interface are the most important in the entire Java.io package. Five classes refer to File, OutputStream, InputStream, Writer, Reader; one interface refers to Serializable. If you master the core operation of these IOs, you will have a preliminary understanding of the IO system in Java.

  Java I/O mainly consists of the following levels, including three parts:

1. Flow mode part - the main part of IO;

2. Non-streaming part - mainly includes some classes of auxiliary streaming part, such as File class, Random Access File class and FileDescriptor class.

3. Other classes - security-related classes in the file reading section, such as the SerializablePermission class and file system classes related to the local operating system, such as FileSystem class and Win32 FileSystem class and WinNTFileSystem class.

The main categories are as follows:

 File (File Characteristics and Management): Descriptive information for a file or directory, such as creating a new directory, modifying the name of the file, deleting the file, and determining the path of the file.

 2. InputStream: An Abstract class, a byte-based input operation, is the parent of all input streams. The common characteristics of all input streams are defined.

 3. OutputStream (binary format operations): Abstract classes. Byte-based output operations. Is the parent of all output streams. The common characteristics of all output streams are defined.

 In Java, characters are represented by Unicode standard, one character is 16 bits, that is, one character is represented by two bytes. To this end, a stream of character processing is introduced in JAVA.

 4. Reader (file format operation): Abstract class, character-based input operation.

 5. Writer (File Format Operation): Abstract class, character-based output operation.

 6. Random Access File (Random File Operation): It is rich in functions and can be accessed (input and output) from any location of the file.

 The architecture of IO flows in Java is shown in the following figure:
  1. Non-streaming file class-File class

In the Java java.io package, File classes provide methods to describe the operation and management of files and directories. However, File class is not a subclass of InputStream, OutputStream or Reader, Writer, because it is not responsible for data input and output, but specifically used to manage disk files and directories.

Function: File class is mainly used for naming files, querying file attributes and processing file directories.
[java] view plain copy
print?

public    class   File   extends Object   
    implements Serializable,Comparable  
{}  

File class provides three different constructors to receive file and directory name information flexibly in the form of different parameters. Constructor:
1)File (String pathname)
Example: File F1 = new File ("FileTest1.txt"); create file object f1, F1 refers to the file created under the current directory FileTest1.txt
2)File (String parent , String child)
Example: File F2 = new File ("D: dir1", "FileTest2.txt"); //Note: The D: dir1 directory must exist beforehand, otherwise it will be abnormal.
3)File (File parent , String child)
Example: File F4 = new File (" dir3");
File F5 = new File (f4, "FileTest 5. txt"); // Create first if dir3 directory does not exist using f4.mkdir()
Once a File object corresponding to a disk file or directory is created, the properties of the file or directory can be obtained by calling it.
1) public boolean exists() to determine whether a file or directory exists
2) public boolean isFile() to determine whether it is a file or a directory
3) Public Boolean is Directory () to determine whether it is a file or a directory
4) public String getName() returns the file name or directory name
5) The path of public String getPath() to return a file or directory.
6) public long length() Gets the length of the file
7) Public String [] list () returns all file names in the directory stored in a string array.
File class also defines some methods to manage and operate files or directories. The common methods are:
1) public Boolean renameTo (File new File); rename files
2) public void delete(); delete files
3) public boolean mkdir(); create directories

Example:

[java] view plain copy
print?

import java.io.File;  
import java.io.IOException;  
public class TestFile {  
    public static void main(String args[]) throws IOException {  
        File dir = new File("\\root");  
        File f1 = new File(dir, "fileOne.txt");  
        File f2 = new File(dir, "fileTwo.java");  
        // When a file object is created, the specified file or directory does not necessarily exist physically.  
        if (!dir.exists())  
            dir.mkdir();  
        if (!f1.exists())  
            f1.createNewFile();  
        if (!f2.exists())  
            f2.createNewFile();  
        System.out.println("f1's AbsolutePath=  " + f1.getAbsolutePath());  
        System.out.println("f1 Canread=" + f1.canRead());  
        System.out.println("f1's len= " + f1.length());  
        String[] FL;  
        int count = 0;  
        FL = dir.list();  
        for (int i = 0; i < FL.length; i++) {  
            count++;  
            System.out.println(FL[i] + "is in \\root");  
        }  
        System.out.println("there are" + count + "file in //root");  
    }  

}  

Description: File class method:
(1) exists() tests whether a specified file or directory exists on disk
(2) mkdir() creates the directory specified by the file object (single-layer directory)
(3) createNewFile() Creates the file specified by the file object

(4) list() returns all file name strings in the directory

  1. Java.IO Stream Class Library
  2. Four basic classes of io flows

    The java.io package contains all the classes required for streaming I/O. There are four basic classes in the java.io package: InputStream, OutputStream and Reader, Writer classes, which deal with byte stream and character stream respectively:

I/O of Basic Data Stream

Input/Output

Byte stream

Character stream

Input stream

Inputstream

Reader

output stream

OutputStream

Writer

IO framework:

Other diverse streams in Java are derived from them:

  JDK version 1.4 has introduced a new I/O class library, which is located in the java.nio package. The new I/O class library uses channels and buffers to improve the efficiency of I/O operations.

  In the java.io package, java.io.InputStream represents the byte input stream, and java.io.OutputStream represents the byte output stream, which is at the top of the java.io package. These two classes are abstract classes, that is to say, they can not be instantiated, they must generate subclasses before they can achieve certain functions.
  1. Concrete classification of io flow

I. Overall classification according to I/O type:

 1. Memory 1) Read and write data from/to memory arrays: CharArray Reader, CharArray Writer, Byte Array Input Stream, Byte Array Output Stream
               2) Read and write data StringReader, StringWriter, StringBuffer InputStream from/to memory strings
 2.Pipe pipeline implements input and output of pipeline (interprocess communication): PipedReader, PipedWriter, PipedInputStream, PipedOutputStream
 3.File file stream. Read and write files: FileReader, FileWriter, FileInputStream, FileOutputStream
 4. ObjectSerialization object input and output: ObjectInputStream, ObjectOutputStream
 5. Data Conversion data streams are read and written by basic data types (data processed is the basic type of Java (such as Boolean, byte, integer and floating point):Data InputStream, Data OutputStream
 6.Printing includes convenient printing methods: PrintWriter, PrintStream
 7.Buffering buffer caches data when it is read in or written out to reduce the number of I/O: Buffered Reader, Buffered Writer, Buffered InputStream, Buffered OutputStream
 8.Filtering filters, which filter data when it is read or written: FilterReader, FilterWriter, FilterInputStream, FilterOutputStream
 9.Concatenation merges inputs to connect multiple input streams into one input stream: SequenceInputStream

Counting counts count rows when reading data: LineNumberReader, LineNumberInputStream
 11.Peeking Ahead prereads through caching: PushbackReader, PushbackInputStream
 12.Converting between Bytes and Characters converts byte streams to character streams according to certain coding/decoding standards, or performs reverse conversion (Stream-to-Reader,Writer conversion classes): InputStream Reader, OutputStream Writer

2. Classification by data source (destination):
File (File): FileInputStream, FileOutputStream, FileReader, FileWriter
2,byte[]: ByteArrayInputStream, ByteArrayOutputStream
3,Char[]: CharArrayReader, CharArrayWriter
4,String: StringBufferInputStream, StringReader, StringWriter
5. Network Data Flow: InputStream, OutputStream, Reader, Writer

  1. Byte stream InputStream/OutputStream

    1. InputStream abstract class

      InputStream is a byte input stream. It is an abstract class. It must rely on its subclasses to implement various functions. This abstract class is a superclass of all classes representing the byte input stream. Streams inherited from InputStream input data into programs in bytes (8bit);

Inputstream is a class for inputting byte data, so the Inputstream class provides three overloaded read methods.
(1) public abstract int read(): Read a byte's data, and the return value is the int type value of the high bit complement 0. If the return value=-1 indicates that no byte reading is completed.
(2) public int read(byte b []): read b.length bytes of data into the b array. The return value is the number of bytes read. This method is actually implemented by calling the next method
(3) public int read (byte b [], int off, int len): read data of len bytes from the input stream and store it in an array b with offset of off.
(4) public int available(): Returns the number of bytes that can be read in the input stream. Note: If the input is blocked, the current thread will be suspended. If the InputStream object calls this method, it only returns 0. This method must be called by a subclass object inheriting the InputStream class.
(5) public long skip(long n): ignoring n bytes in the input stream, the return value is the number of bytes actually ignored, skipping some bytes to read
(6) public int close(): After we use it, we must close the open stream.

     Major subcategories:



     1) FileInputStream regards a file as InputStream to realize the reading operation of the file.     

2) ByteArray InputStream: Use a buffer in memory as an InputStream
3) StringBuffer InputStream: Using a String object as an InputStream
4) PipedInputStream: Implements the concept of pipe, mainly in threads
5) SequenceInputStream: Merge multiple InputStream into one InputStream

2. OutputStream abstract class
OutputStream provides three write methods for data output, which corresponds to InputStream.
1. public void write(byte b []): Writes the bytes in parameter b to the output stream.
2. Public void write (byte b [], int off, int len): Write the len bytes of parameter b from offset off to the output stream.
3. public abstract void write(int b): First convert int to byte type and write low bytes to the output stream.
4. public void flush(): Output all data in the data buffer and empty the buffer.
5. public void close(): Close the output stream and release system resources related to the stream.

   Major subcategories:



  1) ByteArray Output Stream: Store information in a buffer in memory 
  2) FileOutputStream: Store information in a file 
  3) PipedOutputStream: Implements the concept of pipe, mainly in threads 
  4) SequenceOutputStream: Merge multiple OutStreams into one OutStream 

Judgment of the end of the flow: the return value of method read() is - 1; the return value of readLine() is null.
3. File input stream: FileInputStream class

  FileInputStream can read a byte at a time using the read() method and return it as an int type, or read into a byte array when using the read() method. The number of elements in the byte array is as many bytes as it reads. In the process of reading or writing the entire file, such a byte array is usually treated as a buffer, because such a byte array usually acts as an intermediate role to accept data.

Function: Data stream with file as data input source. Or open a file, read data from the file to the memory class.
Usage (1)
File fin=new File("d:/abc.txt");
FileInputStream in=new FileInputStream( fin);

Usage (2)
FileInputStream in=new FileInputStream("d: /abc.txt");

Examples of procedures:
Display the contents of InputFromFile.java programs on the display

[java] view plain copy
print?

import java.io.IOException;  
import java.io.FileInputStream;  
;  
public class TestFile {  
    public static void main(String args[]) throws IOException {  
        try{      
               FileInputStream rf=new   FileInputStream("InputFromFile.java");  
               int n=512;   byte  buffer[]=new  byte[n];     
               while((rf.read(buffer,0,n)!=-1)&&(n>0)){  
                   System.out.println(new String(buffer) );  
                }  
                System.out.println();  
                rf.close();  
        } catch(IOException  IOe){        
              System.out.println(IOe.toString());  
        }  

    }  

}  

4. File output stream: FileOutputStream class
Function: Used to process data streams that use files as data output purposes; or read data into files from memory areas.

  The FileOutputStream class is used to process data streams that use files as data output objects; a string representing file names can also be a File or FileDescriptor object. 

There are two ways to create a file stream object:
Mode 1:
   File f=new File ("d:/myjava/write.txt ");
FileOutputStream out= new FileOutputStream (f);
Mode 2:
  FileOutputStream out=new FileOutputStream("d:/myjava/write.txt ");
Mode 3: The constructor takes the FileDescriptor() object as its parameter.
  FileDescriptor() fd=new FileDescriptor();
  FileOutputStream f2=new FileOutputStream(fd);
Mode 4: The constructor takes the file name as its first parameter and the Boolean value as its second parameter.
  FileOutputStream f=new FileOutputStream("d:/abc.txt",true);
Note: (1) When writing data in a file, if the file already exists, the existing file will be overwritten; (2) When the read/write operation ends, the close method should be called to close the flow.

Program example: Use keyboard to enter an article and save it in the file write.txt

[java] view plain copy
print?

import java.io.IOException;  
import java.io.FileOutputStream;  
public class TestFile {  
    public static void main(String args[]) throws IOException {  
        try {  
            System.out.println("please Input from      Keyboard");  
            int count, n = 512;  
            byte buffer[] = new byte[n];  
            count = System.in.read(buffer);  
            FileOutputStream wf = new FileOutputStream("d:/myjava/write.txt");  
            wf.write(buffer, 0, count);  
            wf.close(); // When the flow write operation ends, the close method is called to close the flow.  
            System.out.println("Save to the write.txt");  
        } catch (IOException IOe) {  
            System.out.println("File Write Error!");  
        }  
    }  

}  
  1. FileInputStream Flow and FileOutputStream Application
    file1.txt is copied to file2.txt by program.
    [java] view plain copy
    print?

    import java.io.File;
    import java.io.IOException;
    import java.io.FileOutputStream;
    import java.io.FileInputStream;

    public class TestFile {
    public static void main(String args[]) throws IOException {
    try {
    File inFile = new File("copy.java");
    File outFile = new File("copy2.java");
    FileInputStream finS = new FileInputStream(inFile);
    FileOutputStream foutS = new FileOutputStream(outFile);
    int c;
    while ((c = finS.read()) != -1) {
    foutS.write(c);
    }
    finS.close();
    foutS.close();
    } catch (IOException e) {
    System.err.println("FileStreamsTest: " + e);
    }
    }

    }

  2. Buffered Input Stream / Buffered Output Stream

    Computer access to external devices is time-consuming. The higher the frequency of accessing external memory, the greater the probability of CPU idleness. In order to reduce the number of accesses to external memory, more data should be read and written in one access to peripherals. For this reason, besides the necessary read-write mechanism for exchanging data between programs and stream nodes, buffer mechanism should also be added. A buffer stream is a buffer allocated to each data stream, and a buffer is a memory that temporarily stores data. This can reduce the number of accesses to the hard disk and improve the transmission efficiency.

Buffered Input Stream: When data is written to the buffer stream, the data is written to the buffer first. When the buffer is full, the system sends the data to the output device at one time.

Buffered Output Stream: When reading data from the buffer stream, the system reads data from the buffer first, and when the buffer is empty, the system reads data from the input device to the buffer.
1) Read the file into memory:

Connect Buffered Input Stream with FileInput Stream

FileInputStream in=new FileInputStream( "file1.txt " );

BufferedInputStream bin=new BufferedInputStream( in);

2) Write memory to a file:

Connect Buffered Output Stream with FileOutput Stream

FileOutputStreamout=new FileOutputStream("file1.txt");

BufferedOutputStream bin=new BufferedInputStream(out);

3) Keyboard input stream read to memory
Connect BufferedReader with standard data streams
InputStreamReader sin=new InputStreamReader (System.in) ;
BufferedReader bin=new BufferedReader(sin);
[java] view plain copy
print?

import java.io.*;  

public class ReadWriteToFile {  
    public static void main(String args[]) throws IOException {  
        InputStreamReader sin = new InputStreamReader(System.in);  
        BufferedReader bin = new BufferedReader(sin);  
        FileWriter out = new FileWriter("myfile.txt");  
        BufferedWriter bout = new BufferedWriter(out);  
        String s;  
        while ((s = bin.readLine()).length() > 0) {  
            bout.write(s, 0, s.length());  
        }  

    }  
}  

Procedure description:
The method of reading characters from the keyboard and writing them to the BufferedReader class in the file: String readLine()
Function: Read a line of string, ending with a carriage return character.
Method of the BufferedWriter class: bout. write (String, offset, len)
What it does: Start with offset from the buffer, and write len-length strings somewhere.

  1. Character stream Writer/Reader

    In Java, characters are represented by Unicode standard, one character is 16 bits, that is, one character is represented by two bytes. To this end, a stream of character processing is introduced in JAVA.
    
  2. Reader abstract class

    An abstract class for reading character streams. The only methods that subclasses must implement are read(char[], int, int) and close(). However, most subclasses will override some of the methods defined here to provide greater efficiency and/or other functionality.

    1) FileReader: corresponding to FileInputStream  
       Mainly used to read character files, using the default character encoding, there are three constructors: 
    

    (1) File name as string: FileReader f=new FileReader("c:/temp.txt");
    (2) The constructor takes the File object as its parameter.
       File f=new file("c:/temp.txt");
       FileReader f1=new FileReader(f);
    (3) The constructor takes the FileDescriptor object as a parameter
       FileDescriptor() fd=new FileDescriptor()
       FileReader f2=new FileReader(fd);
    (1) Use the specified character array as a parameter: CharArray Reader (char [])
    (2) Use character arrays as input streams: CharArray Reader (char [], int, int)
    Read the string, the constructor is as follows: public StringReader(String s);
    2) Char Array Reader: corresponding to Byte Array Input Stream
    3) StringReader: corresponding to StringBuffer Input Stream
      4) InputStreamReader
    Read bytes from the input stream and convert them into characters: Public inputstreamReader(inputstream is);
    5) FilterReader: allows filtering of character streams
       protected filterReader(Reader r);
    6) BufferReader: Accept the Reader object as a parameter, and add a character buffer to it, using the readline() method can read a line.
       Public BufferReader(Reader r);

    Main methods:

    (1) Public int read () throws IOException; // Reads a character and returns a character read.

    (2) Public int read (char cbuf []) throws IOException; / Reads a series of characters into the array cbuf [], returns the number of characters actually read/
      (3) public abstract int read(char cbuf[],int off,int len) throws IOException;
    / Read len characters, store them from the subscript off of the array cbuf [] and return the number of characters actually read. This method must be implemented by subclasses./

  3. Writer abstract class

    Write abstract classes to character streams. The only methods that a subclass must implement are write(char[], int, int), flush(), and close(). However, most subclasses will override some of the methods defined here to provide greater efficiency and/or other functionality. Its subcategories are as follows:

    1) FileWrite: Corresponding to FileOutput Stream
    Write character type data to a file, using default character encoding and buffer size.
      Public FileWrite(file f);
    2) ChararrayWrite: Corresponding to ByteArray Output Stream, the character buffer is used as the output.
       Public CharArrayWrite();
    3) PrintWrite: Generating formatted output
       public PrintWriter(outputstream os);
    4) filterWriter: Used for writing filtered character streams
       protected FilterWriter(Writer w);
    5) PipedWriter: corresponding to PipedOutput Stream

    6) StringWriter: No corresponding byte-oriented stream

    Main methods:

    (1) Public void write (int c) throws IOException; //Writes the lower 16 bits of integer value C to the output stream
    (2) Public void write (char cbuf []) throws IOException; //Writes character array cbuf [] to the output stream
    (3) Public Abstract void write (char cbuf [], int off, int len) throws IOException; //Writes the len character in the character array cbuf [] from the position where the index is off to the output stream.
    (4) Public void write (String str) throws IOException; // Writes characters in the string STR to the output stream
    (5) Public void write (String str, int off, int len) throws IOException; //Writes the len characters in the string STR from the beginning of index off to the output stream
    (6) Flush ()// flush the output stream and output all cached bytes.
    (7)close() closed stream public abstract void close() throws IOException

3. InputStream and Reader Differences OutputStream and Writer Differences

InputStream and OutputStream classes deal with byte streams, and the smallest unit of data streams is bytes (8 bits).
Reader and Writer deal with character stream, which involves the conversion of character encoding.

[java] view plain copy
print?

import java.io.*;  
public class EncodeTest {  
    private static void readBuff(byte [] buff) throws IOException {  
       ByteArrayInputStream in =new ByteArrayInputStream(buff);  
        int data;  
        while((data=in.read())!=-1)   System.out.print(data+"  ");  
        System.out.println();     in.close();     }  

   public static void main(String args[]) throws IOException {  
       System.out.println("In-memory adoption unicode Character encoding:" );  
       char   c='good';  
       int lowBit=c&0xFF;     int highBit=(c&0xFF00)>>8;  
       System.out.println(""+lowBit+"   "+highBit);  
       String s="good";  
       System.out.println("Default character encoding for local operating system:");  
       readBuff(s.getBytes());  
       System.out.println("Use GBK Character encoding:");  
       readBuff(s.getBytes("GBK"));  
       System.out.println("Use UTF-8 Character encoding:");        
       readBuff(s.getBytes("UTF-8"));      }  
}  

The Reader class can convert characters of other encoding types into Unicode characters in the input stream and allocate memory to them in memory.

The Writer class can convert Unicode characters in memory into characters of other encoding types and write them to the output stream.

  1. FileWriter class (character output stream class)

Constructor: FileWriter fw = new FileWriter(String fileName); // Create character output stream class objects associated with existing files. If the file does not exist, create it.

           Such as: FileWriter fw = new FileWriter("C:\\1.txt");

             FileWriter fw = new FileWriter(String fileName,boolean append);//Create a character output stream class object associated with an existing file, and set whether the stream's operation on the file is a continuation.

           //For example: FileWriter fw = new FileWriter("C:\1.txt",ture); // means that when fw writes a file again, it will continue at the end of the file and will not be overwritten.

Main methods:

    void write(String str)   //Write a string. When this method is executed, the character data is not written to the destination file. Character data is saved in the buffer. In this case, the data can be saved to the destination file by using refresh method.

    viod flush()                //Refresh buffers in the stream. Save the character data in the buffer to the destination file.

    viod close()               //Close this stream. The buffer of this stream is refreshed before closing. If you write or refresh after closing, an IOException exception will be thrown.
  1. How to Choose IO Flow

    1) Determine the data source and data purpose (input or output)

          Source: Input Stream Reader
          Purpose: Output Stream Writer
    

    2) Is the data object explicitly manipulated plain text?

         Yes: Character Stream Reader, Writer
         No: byte stream InputStream, OutputStream
    

    3) Define the specific equipment.

         Is a hard disk file: File++:
    
         Read: FileInputStream, FileReader, 
    
          Write: FileOutputStream, FileWriter
         Is an array for memory
    
              byte[]: ByteArrayInputStream, ByteArrayOutputStream
              It's char []: Char Array Reader, Char Array Writer
         String: String Buffer Input Stream (obsolete, because it can only be used for String with each character being an 8-bit string), String Reader, String Writer
         Socket Stream for Network
    
         It's the keyboard: read with System.in (an InputStream object) and print with System.out (an OutoutStream object)
    

    3) Need to convert streams

        Yes, using the transformation stream, from Stream to Reader, Writer: InputStream Reader, OutputStream Writer 
    

    4) Whether buffer is needed to improve efficiency

    Yes, add Buffered: Buffered Input Stream, Buffered Ouput Stream, BuffereaReader, Buffered Writer.
    5) Whether formatted output is required

Example: Store data in one text file into another file.
1) Data source and data purpose: read stream, InputStream Reader output: OutputStream Writer
2) Pure text: Yes! Then you can choose Reader Writer.
3) Equipment: Hard disk files. FileReader FileWriter is the object that can manipulate files in Reader system.

        FileReader fr = new FileReader("a.txt");  

         FileWriter fw = new FileWriter("b.txt");  
 4)Need to improve efficiency: Yes, plus Buffer
         BufferedReader bfr = new BufferedReader(new FileReader("a.txt");  );  
         BufferedWriter bfw = new BufferedWriter(new FileWriter("b.txt");  );  
  1. Subclasses of IOException exception classes

1.public class EOFException :
This type of exception is thrown when the end of the file or input stream reaches abnormally.
2.public class FileNotFoundException:
An exception thrown when the file cannot be found.
3.public class InterruptedIOException:
When I/O operations are interrupted, this type of exception is thrown

11. The component Activity in Android can specify the parameter android: ConfigChanges in the manifest.xml file to capture changes in the status of the mobile phone.
The android:configChanges property is added to Activity, and when the specified property (Configuration Changes) changes, the notification program calls the onConfiguration Changed () function.

Setup: Separate the following fields with the "|" symbol, such as "locale|navigation|orientation"

"Mcc" mobile country number, consisting of three digits, each country has its own independent MCC, which can identify the country of mobile phone users.
"mnc" mobile network number, in a country or region, is used to differentiate the service providers of mobile phone users.
locale has changed in its area.
The touch screen has changed. (This shouldn't happen often.)
"Keyboard" keyboard mode changes, for example: users access external keyboard input.
"Keyboard Hidden" Users Open Mobile Hardware Keyboard
navigation has changed. (This shouldn't happen often.)
"orientation" device rotation, horizontal display and vertical display mode switching.
"Font Scale" Global font size scaling changed

For Android:configChanges attributes, the following are generally considered:
1. When the android:configChanges of Activity is not set, the screen-cutting will call each life cycle again, and it will be executed once when cutting the horizontal screen and twice when cutting the vertical screen.

2. When setting up the android:configChanges= "orientation" of Activity, the screen-cutting will call each life cycle again, and only once will be executed when the screen is cut horizontally or vertically.

3. When setting up android:configChanges= "orientation | keyboard Hidden" of Activity, the screen-cutting will not call each life cycle again, but will only execute the onConfiguration Changed method.

However, since Android 3.2 (API 13), after setting up the android:configChanges= "orientation | keyboard Hidden" of Activity, all life cycles will be re-invoked. Because screen size also began to change with the vertical and horizontal switching of the device. So, if the MiniSdkVersion and TargetSdkVersion attributes set in Android Manifest. XML are greater than or equal to 13, if you want to prevent the program from reloading Activity at run time, you must also set ScreenSize in addition to orientation.
Solution:
Set android:configChanges="orientation|screenSize in Android Manifest. xml“

12.message.obj passes multiple parameters
Bean.java:

public class Bean {
public Bitmap bitmap;
public HashMap

Topics: Android Fragment Java encoding