{"id":695,"date":"2023-09-04T20:50:15","date_gmt":"2022-09-09T14:49:08","guid":{"rendered":"https:\/\/www.silicloud.com\/zh\/blog\/index.php\/2023\/11\/30\/android%e9%9d%a2%e8%af%95%e9%97%ae%e9%a2%98%e4%b8%8e%e5%9b%9e%e7%ad%94\/"},"modified":"2025-08-03T03:29:23","modified_gmt":"2025-08-02T19:29:23","slug":"android%e9%9d%a2%e8%af%95%e9%97%ae%e9%a2%98%e4%b8%8e%e5%9b%9e%e7%ad%94","status":"publish","type":"post","link":"https:\/\/www.silicloud.com\/zh\/blog\/android%e9%9d%a2%e8%af%95%e9%97%ae%e9%a2%98%e4%b8%8e%e5%9b%9e%e7%ad%94\/","title":{"rendered":"2023\u6700\u65b0Android\u9762\u8bd5\u95ee\u9898\u4e0e\u56de\u7b54\u5927\u5168\uff1a\u9762\u8bd5\u5b98\u6700\u7231\u95ee\u768450\u9053\u9898\u8be6\u89e3"},"content":{"rendered":"<p>Android\u662f\u624b\u673a\u4e0a\u6700\u53d7\u6b22\u8fce\u7684\u64cd\u4f5c\u7cfb\u7edf\u3002\u5982\u4ecaAndroid\u5e94\u7528\u975e\u5e38\u6d41\u884c\u3002\u7531\u4e8eAndroid\u662f\u5f00\u6e90\u7684\uff0c\u56e0\u6b64\u975e\u5e38\u53d7\u6b22\u8fce\uff0c\u4efb\u4f55\u4eba\u90fd\u53ef\u4ee5\u521b\u5efaAndroid\u5e94\u7528\u3002\u6709\u5f88\u591a\u516c\u53f8\u4e13\u95e8\u81f4\u529b\u4e8e\u5f00\u53d1Android\u5e94\u7528\u3002\u6211\u5199\u8fc7\u5f88\u591a\u5173\u4e8eAndroid\u7684\u6559\u7a0b\uff0c\u8fd9\u91cc\u6211\u5217\u51fa\u4e86\u4e00\u4e9b\u91cd\u8981\u7684Android\u9762\u8bd5\u95ee\u9898\uff0c\u4ee5\u5e2e\u52a9\u4f60\u5728\u9762\u8bd5\u4e2d\u3002<\/p>\n<h2>Android\u9762\u8bd5\u95ee\u9898<\/p>\n<div>\n                            <img decoding=\"async\" src=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/65647fd4a4b2f92e6c72df8e\/2-0.jpg\" class='post-images' alt=\"android interview questions\" title=\"\"><\/p>\n<ol>\u5f53\u5c4f\u5e55\u65b9\u5411\u6539\u53d8\u65f6\uff0c\u4e0a\u8ff0\u5e94\u7528\u7a0b\u5e8f\u4f1a\u91cd\u65b0\u521b\u5efa\u65b0\u7684Activity\u5b9e\u4f8b\uff0c\u6b64\u65f6\u4f1a\u91cd\u65b0\u8c03\u7528onCreate()\u65b9\u6cd5\u3002\u56e0\u6b64\uff0c\u5f53\u5c4f\u5e55\u65b9\u5411\u6539\u53d8\u65f6\uff0cTextView\u7684\u503c\u5c06\u88ab\u91cd\u7f6e\u4e3a0\uff0c\u56e0\u4e3ai\u7684\u521d\u59cb\u503c\u4e3a0\u3002<\/ol>\n<pre class=\"post-pre\"><code>On-screen rotation the activity restarts and the objects are initialized again. Hence the textView counter resets to zero every time the orientation is changed.\r\n<\/code><\/pre>\n<ol>\u5f53\u5c4f\u5e55\u65cb\u8f6c\u65f6\uff0c\u5982\u4f55\u9632\u6b62\u6570\u636e\u91cd\u65b0\u52a0\u8f7d\u548c\u91cd\u7f6e\uff1f<\/ol>\n<pre class=\"post-pre\"><code>The most basic approach is to add an element attribute tag `android:configChanges` inside the activity tag in the AndroidManifest.xml as shown below.\r\n\r\n```\r\n&lt;activity android:name=\".MainActivity\"\r\n\t android:configChanges=\"orientation|screenSize\"&gt;\r\n\t\r\n\t&lt;intent-filter&gt;\r\n\t  \t &lt;action android:name=\"android.intent.action.MAIN\" \/&gt;\r\n\t  \t &lt;category android:name=\"android.intent.category.LAUNCHER\" \/&gt;\r\n    &lt;\/intent-filter&gt;\r\n    \r\n&lt;\/activity&gt;            \r\n```\r\n\r\nIn general, the configChanges for any activity are defined as\r\n\r\n```\r\nandroid:configChanges=\"orientation|screenSize|keyboardHidden\"\r\n```\r\n\r\nThe `keyboardHidden` configuration is to prevent the keyboard from resetting if it's pulled out.\r\n<\/code><\/pre>\n<ol>\u4ee5\u4e0b\u662factivity_main.xml\u7684\u793a\u4f8b\u5e03\u5c40\u3002MainActivity.java\u53ea\u5305\u542b\u7a7a\u7684onCreate()\u65b9\u6cd5\u3002<\/ol>\n<pre class=\"post-pre\"><code>```\r\n&lt;?xml version=\"1.0\" encoding=\"utf-8\"?&gt;\r\n&lt;RelativeLayout xmlns:android=\"https:\/\/schemas.android.com\/apk\/res\/android\"\r\n\tandroid:layout_width=\"match_parent\"\r\n\tandroid:layout_height=\"match_parent\"\r\n\tandroid:paddingBottom=\"@dimen\/activity_vertical_margin\"\r\n \tandroid:paddingLeft=\"@dimen\/activity_horizontal_margin\"\r\n \tandroid:paddingRight=\"@dimen\/activity_horizontal_margin\"\r\n \tandroid:paddingTop=\"@dimen\/activity_vertical_margin\"\r\n&gt;\r\n \r\n  &lt;EditText\r\n \tandroid:layout_width=\"wrap_content\"\r\n \tandroid:layout_height=\"wrap_content\"\r\n \tandroid:text=\"Hello World!\"\r\n \tandroid:layout_alignParentRight=\"true\"\r\n \tandroid:layout_alignParentEnd=\"true\"\r\n \tandroid:layout_alignParentLeft=\"true\"\r\n \tandroid:layout_alignParentStart=\"true\" \/&gt;\r\n\r\n&lt;\/RelativeLayout&gt;\r\n```\r\n\r\nThe configChanges are defined in the AndroidManifest.xml as `android:configChanges=\"orientation|screenSize|keyboardHidden\"`\r\n\r\n#### Does the input text entered in the EditText persist when the orientation is changed? Yes\/No? Explain.\r\n\r\nNo. Despite the configChanges defined in the AndroidManifest.xml, the EditText input text entered resets when the orientation is changed. This is because no resource id has been defined. On orientation change, the instance of the EditText gets lost. To fix this issue to work correctly add an `android:id` attribute element in the EditText tag.\r\n<\/code><\/pre>\n<ol>\u4e3a\u4ec0\u4e48\u4e0d\u63a8\u8350\u4f7f\u7528android:configChanges\uff1f\u6709\u66f4\u597d\u7684\u5904\u7406\u5c4f\u5e55\u65cb\u8f6c\u7684\u65b9\u5f0f\u5417\uff1f<\/ol>\n<pre class=\"post-pre\"><code>`android:configChanges` is not the recommended way by Google. Though it's the simplest way to use, it comes with its own share of drawbacks. First, the common perception that android:configChanges = \"orientation\" will magically retain the data is a complete misinterpretation. The orientation changes can occur from a number of other events such as changing the default language can trigger a configuration change and destroy and recreate the activity. Second, the activity can restart itself if it's in the background and Android decides to free up its heap memory by killing it. When the application returns to the foreground it'll restart it's data to the original state and the user may not like that. A better alternative of `android:configChanges` is; Saving the current state of the activity when it's being destroyed and restoring the valuable data when it's restarted can be done by overriding the methods `onSaveInstanceState()` and `onRestoreInstanceState()` of the activity class.\r\n<\/code><\/pre>\n<ol>\u5728\u6d3b\u52a8\u751f\u547d\u5468\u671f\u4e2d\uff0conSaveInstanceState()\u548conRestoreInstanceState()\u65b9\u6cd5\u662f\u5728\u4ec0\u4e48\u65f6\u5019\u4f7f\u7528\u7684\uff1f\u8fd9\u4e9b\u65b9\u6cd5\u5982\u4f55\u4fdd\u5b58\u548c\u6062\u590d\u6570\u636e\uff1f<\/ol>\n<pre class=\"post-pre\"><code>In general the onSaveInstanceState() is invoked after onPause() and before the onStop(). But the API documentation explicitly states that the onSaveInstanceState( ) method will be called before onStop() but makes no guarantees it will be called before or after onPause(). The onRestoreInstanceState() is called after onStart() is invoked. The onRestoreInstanceState() method is invoked only when the activity was killed before. If the activity is NOT killed the onSaveInstanceState() is NOT called. When the activity is being destroyed, the onSaveInstanceState() gets invoked. The onSaveInstanceState contains a Bundle parameter. The data to be saved is stored in the bundle object in the form of a HashMap. The bundle object is like a custom HashMap object. The data is retrieved in the onRestoreInstanceState() method using the keys.\r\n<\/code><\/pre>\n<ol>\u4f60\u88ab\u7ed9\u4e88\u4e00\u4e2a\u5305\u542b\u4e00\u4e2aEditText\u5b57\u6bb5\u7684\u5e03\u5c40\u3002\u5b9e\u73b0onSaveInstanceState()\u548conRestoreInstanceState()\u51fd\u6570\uff0c\u5f53\u5c4f\u5e55\u65cb\u8f6c\u65f6\uff0c\u4fdd\u5b58\u548c\u6062\u590d\u5f53\u524d\u8f93\u5165\u7684\u6587\u672c\uff0c\u800c\u4e0d\u9700\u8981\u5728\u6e05\u5355\u6587\u4ef6\u4e2d\u58f0\u660eandroid:configChanges\u5c5e\u6027\u3002\u4e0b\u9762\u7ed9\u51fa\u4e86MainActivity.java\u3002<\/ol>\n<pre class=\"post-pre\"><code>```\r\n \r\npublic class MainActivity extends AppCompatActivity {\r\n    EditText editText;\r\n    @Override\r\n    protected void onCreate(Bundle savedInstanceState) {\r\n        super.onCreate(savedInstanceState);\r\n        setContentView(R.layout.activity_main);\r\n\r\n        editText = (EditText) findViewById(R.id.editText);\r\n    }\r\n}\r\n```\r\n\r\n```\r\n \r\npublic class MainActivity extends AppCompatActivity {\r\n    EditText editText;\r\n    @Override\r\n    protected void onCreate(Bundle savedInstanceState) {\r\n        super.onCreate(savedInstanceState);\r\n        setContentView(R.layout.activity_main);\r\n        editText = (EditText) findViewById(R.id.editText);\r\n    }\r\n    @Override\r\n    public void onSaveInstanceState(Bundle outState) {\r\n        super.onSaveInstanceState(outState);\r\n        outState.putString(\"myData\", editText.getText().toString());\r\n    }\r\n    @Override\r\n    protected void onRestoreInstanceState(Bundle savedInstanceState) {\r\n        super.onRestoreInstanceState(savedInstanceState);\r\n        editText.setText(savedInstanceState.getString(\"myData\"));\r\n    }\r\n}\r\n```\r\n<\/code><\/pre>\n<ol>\u5982\u4f55\u4fdd\u6301\u5c4f\u5e55\u5b9a\u5411\u56fa\u5b9a\uff1f\u540c\u65f6\uff0c\u5728\u7279\u5b9a\u6d3b\u52a8\u4e2d\u5b9e\u73b0\u5c4f\u5e55\u59cb\u7ec8\u4fdd\u6301\u4eae\u8d77\u7684\u673a\u5236\u3002<\/ol>\n<pre class=\"post-pre\"><code>The screen orientation can be fixed by adding the attribute `android:screenOrientation=\"portrait\"` or `android:screenOrientation=\"landscape\"` in the activity tag. To keep the screen always on for a particular screen add the `android:keepScreenOn=\"true\"` in the root tag of the activity layout.\r\n<\/code><\/pre>\n<ol>\u5982\u4f55\u901a\u8fc7\u7f16\u7a0b\u65b9\u5f0f\u91cd\u65b0\u542f\u52a8\u4e00\u4e2a\u6d3b\u52a8\uff1f\u5728\u6309\u94ae\u70b9\u51fb\u65f6\uff0c\u5b9e\u73b0\u4e00\u4e2a\u540d\u4e3arestartActivity()\u7684\u65b9\u6cd5\u6765\u91cd\u65b0\u542f\u52a8\u4e00\u4e2a\u6d3b\u52a8\u3002<\/ol>\n<pre class=\"post-pre\"><code>Given below is the MainActivity.java class\r\n\r\n```\r\n \r\npublic class MainActivity extends AppCompatActivity {\r\n    Button btn;\r\n    @Override\r\n    protected void onCreate(Bundle savedInstanceState) {\r\n        super.onCreate(savedInstanceState);\r\n        setContentView(R.layout.activity_main);\r\n        \r\n        btn = (Button) findViewById(R.id.btn);\r\n\r\n        btn.setOnClickListener(new View.OnClickListener() {\r\n            @Override\r\n            public void onClick(View v) {\r\n\r\n                restartActivity();\r\n\r\n            }\r\n        });\r\n    }\r\n\r\n    public void restartActivity() {\r\n        \/\/Complete the code\r\n    }\r\n\r\n}\r\n```\r\n\r\nWe need to invoke the recreate method on the Activity instance as shown below.\r\n\r\n```\r\npublic void restartActivity() {\r\n        MainActivity.this.recreate();\r\n    }\r\n```\r\n<\/code><\/pre>\n<ol>\u63cf\u8ff0&#8221;\u610f\u56fe&#8221;\u7684\u4e09\u79cd\u5e38\u89c1\u7528\u6cd5\u4ee5\u53ca\u5b83\u4eec\u5982\u4f55\u88ab\u8c03\u7528\u3002<\/ol>\n<pre class=\"post-pre\"><code>Android Intents are used to\r\n1.  start an activity - startActivity(intent)\r\n2.  start a service - startService(intent)\r\n3.  deliver a broadcast - sendBroadcast(intent)\r\n<\/code><\/pre>\n<ol>\u4f7f\u7528\u610f\u56fe\u5b9e\u73b0\u4e24\u4e2a\u64cd\u4f5c\uff0c\u5206\u522b\u662f\u62e8\u6253\u7535\u8bdd\u548c\u6253\u5f00\u4e00\u4e2aURL\u94fe\u63a5\u3002<\/ol>\n<pre class=\"post-pre\"><code>To enable calling from the application we need to add the following permission in the manifest tag of AndroidManifest.xml\r\n\r\n```\r\n&lt;uses-permission android:name=\"android.permission.CALL_PHONE\" \/&gt;\r\n```\r\n\r\nIn the MainActivity the following code invokes an action call to the given number represented as a string. The string is parsed as a URI.\r\n\r\n```\r\n\r\nString phone_number = \"XXXXXXX\" \/\/ replace it with the number\r\n\r\nIntent intent=new Intent(Intent.ACTION_CALL,Uri.parse(\"tel:\"+phone number);\r\nstartActivity(intent);\r\n```\r\n\r\nTo open a URL we need to add the following permission.\r\n\r\n```\r\n&lt;uses-permission android:name=\"android.permission.INTERNET\" \/&gt;\r\n```\r\n\r\nThe intent to view a URL is defined below.\r\n\r\n```\r\nIntent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(\"https:\/\/www.scdev.com\/\"));\r\nstartActivity(intent);\r\n```\r\n<\/code><\/pre>\n<ol>Intent\u5bf9\u8c61\u7684setFlags()\u548caddFlags()\u4e4b\u95f4\u6709\u4ec0\u4e48\u533a\u522b\uff1f<\/ol>\n<pre class=\"post-pre\"><code>When we're using setFlags, we're replacing the old flags with a new set of Flags. When we use addFlags, we're appending more flags.\r\n<\/code><\/pre>\n<ol>\u5728\u4f7f\u7528\u610f\u56fe\u8c03\u7528\u65b0\u6d3b\u52a8\u65f6\uff0c\u63d0\u5230\u4e24\u79cd\u6e05\u9664\u6d3b\u52a8\u8fd4\u56de\u5806\u6808\u7684\u65b9\u6cd5\u3002<\/ol>\n<pre class=\"post-pre\"><code>The first approach is to use a `FLAG_ACTIVITY_CLEAR_TOP` flag.\r\n\r\n```\r\nIntent intent= new Intent(ActivityA.this, ActivityB.class);\r\nintent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);\r\nstartActivity(intent);\r\nfinish();\r\n```\r\n\r\nThe second way is by using `FLAG_ACTIVITY_CLEAR_TASK` and `FLAG_ACTIVITY_NEW_TASK` in conjunction.\r\n\r\n```\r\nIntent intent= new Intent(ActivityA.this, ActivityB.class);\r\nintent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);\r\nstartActivity(intent);\r\n```\r\n<\/code><\/pre>\n<ol>FLAG_ACTIVITY_CLEAR_TASK\u548cFLAG_ACTIVITY_CLEAR_TOP\u4e4b\u95f4\u6709\u4ec0\u4e48\u533a\u522b\uff1f<\/ol>\n<pre class=\"post-pre\"><code>`FLAG_ACTIVITY_CLEAR_TASK` is used to clear all the activities from the task including any existing instances of the class invoked. The Activity launched by intent becomes the new root of the otherwise empty task list. This flag has to be used in conjunction with `FLAG_ ACTIVITY_NEW_TASK`. `FLAG_ACTIVITY_CLEAR_TOP` on the other hand, if set and if an old instance of this Activity exists in the task list then barring that all the other activities are removed and that old activity becomes the root of the task list. Else if there's no instance of that activity then a new instance of it is made the root of the task list. Using `FLAG_ACTIVITY_NEW_TASK` in conjunction is a good practice, though not necessary.\r\n<\/code><\/pre>\n<ol>\u8bf7\u7ed9\u51fa\u4e00\u4e2a\u4f7f\u7528FLAG_ACTIVITY_NEW_TASK\u7684\u7528\u4f8b\uff0c\u5e76\u63cf\u8ff0\u8be5\u6d3b\u52a8\u5982\u4f55\u54cd\u5e94\u8be5\u6807\u5fd7\u3002<\/ol>\n<pre class=\"post-pre\"><code>When we're trying to launch an activity from outside the activity's context, a FLAG\\_ACTIVITY\\_NEW\\_TASK is compulsory else a runtime exception would be thrown. Example scenarios are: launching from a service, invoking an activity from a notification click. If the activity instance is already on the task list when the flag is set, it will invoke the onNewIntent() method of that Activity. All the implementation stuff goes in that method.\r\n<\/code><\/pre>\n<ol>\u5b9a\u4e49 Activity \u7684 launchMode \u7c7b\u578b\uff0c\u5e76\u63cf\u8ff0\u6bcf\u79cd\u7c7b\u578b\u7684\u542b\u4e49\u3002<\/ol>\n<pre class=\"post-pre\"><code>The `android:launchMode` of an Activity can be of the following types:\r\n-   **standard** : It's the default launch mode for an activity wherein every new instance of the activity called will be put on top of the stack as a separate entity. Hence calling startActivity() for a particular class 10 times will create 10 activities in the task list.\r\n-   **singleTop**: It differs from the standard launch mode in the fact that when the Activity instance that's invoked is already present on the top of the stack, instead of creating a new Activity, that instance will be called. In cases where the same Activity instance is not on the top of the stack or if it doesn't exist in the stack at all then a new instance of the activity will be added to the stack. Hence we need to handle the upcoming intent in both the `onCreate()` and `onNewIntent()` methods to cover all cases.\r\n-   **singleTask**: This is different from singleTop in the case that if the Activity instance is present in the stack, the onNewIntent() would be invoked and that instance would be moved to the top of the stack. All the activities placed above the singleTask instance would be destroyed in this case. When the activity instance does not exist in the stack, the new instance would be placed on the top of the stack similar to the standard mode.\r\n-   **singleInstance** : An activity with this launchMode defined would place only a singleton activity instance in the Task. The other activities of the application will be placed in a separate Task.\r\n<\/code><\/pre>\n<ol>\u4efb\u52a1\u4eb2\u548c\u6027\u662f\u4ec0\u4e48\u610f\u601d\uff1f<\/ol>\n<pre class=\"post-pre\"><code>\r\n\r\n```\r\nEditText in;\r\n\r\nin=(EditText)findViewById(R.id.editText);\r\n        if (in != null) {\r\n            in.setSelection(Integer.parseInt(String.valueOf(in.getText().toString().length())));\r\n        }\r\n```\r\n\r\nThe setSelection method requires an integer parameter. So we're wrapping the length of the string as an Integer using parseInt.\r\n<\/code><\/pre>\n<ol>\u5b9e\u73b0\u4e00\u4e2aEditText\uff0c\u5728\u6309\u4e0b\u56de\u8f66\u952e\u65f6\u81ea\u52a8\u6e05\u7a7a\u3002\u4e0b\u9762\u7684\u56fe\u7247\u5c55\u793a\u4e86\u8fd9\u4e2a\u8981\u6c42\u3002<\/ol>\n<pre class=\"post-pre\"><code>\r\n\r\n```\r\nEditText in;\r\nin=(EditText)findViewById(R.id.editText);\r\n\r\n        in.addTextChangedListener(new TextWatcher() {\r\n            @Override\r\n            public void beforeTextChanged(CharSequence s, int start, int count, int after) {\r\n\r\n            }\r\n\r\n            @Override\r\n            public void onTextChanged(CharSequence s, int start, int before, int count) {\r\n                String string = s.toString();\r\n                if (string.length() &gt; 0 &amp;&amp; string.charAt(string.length() - 1) == '\\n') {\r\n                    Toast.makeText(getApplicationContext(),\"ENTER KEY IS PRESSED\",Toast.LENGTH_SHORT).show();\r\n                    in.setText(\"\");\r\n                }\r\n            }\r\n\r\n            @Override\r\n            public void afterTextChanged(Editable s) {\r\n\r\n            }\r\n        });\r\n\r\n```\r\n<\/code><\/pre>\n<ol>\u89e3\u91caLinearLayout\u3001RelativeLayout\u548cAbsoluteLayout\u4e4b\u95f4\u7684\u533a\u522b\u3002<\/p>\n<p>\u533a\u5206LinearLayout\u3001RelativeLayout\u548cAbsoluteLayout\u3002<\/ol>\n<pre class=\"post-pre\"><code>A LinearLayout arranges its children in a single row or single column one after the other. A RelativeLayout arranges it's children in positions relative to each other or relative to parent depending upon the LayoutParams defined for each view. AbsoluteLayout needs the exact positions of the x and y coordinates of the view to position it. Though this is deprecated now.\r\n<\/code><\/pre>\n<ol>FrameLayout\u548cTableLayout\u6709\u4ec0\u4e48\u533a\u522b\uff1f<\/ol>\n<pre class=\"post-pre\"><code>A FrameLayout stack up child views above each other with the last view added on the top. Though we can control the position of the children inside the FrameLayout using the layout\\_gravity attribute. When the width and height of the FrameLayout are set to wrap\\_content, the size of the FrameLayout equals the size of the largest child (plus padding). A TableLayout consists of TableRows. The children are arranged in the form of rows and columns.\r\n<\/code><\/pre>\n<ol>\u6570\u636e\u662f\u5982\u4f55\u5b58\u50a8\u5728Shared Preferences\u4e2d\u7684\uff1fcommit()\u548capply()\u6709\u4ec0\u4e48\u533a\u522b\uff1f\u54ea\u4e2a\u662f\u63a8\u8350\u7684\uff1f<\/ol>\n<pre class=\"post-pre\"><code>Data is stored in SharedPreferences in the form of a key-value pair(HashMap). commit() was introduced in API 1 whereas apply() came up with API 9. commit() writes the data synchronously and returns a boolean value of success or failure depending on the result immediately. apply() is asynchronous and it won't return any boolean response. Also, if there is an apply() outstanding and we perform another commit(), then the commit() will be blocked until the apply() is not completed. commit() is instantaneous and performs disk writes. If we're on the main UI thread apply() should be used since it's asynchronous.\r\n<\/code><\/pre>\n<ol>\u5f53\u7528\u6237\u5728\u5c4f\u5e55\u4e0a\u6309\u4e0b\u8fd4\u56de\u6309\u94ae\u65f6\uff0c\u4f1a\u8c03\u7528\u54ea\u79cd\u65b9\u6cd5\uff1f<\/ol>\n<pre class=\"post-pre\"><code>The onBackPressed() method of the Activity is invoked. Unless overridden it removes the current activity from the stack and goes to the previous activity.\r\n<\/code><\/pre>\n<ol>\u4f60\u5982\u4f55\u7981\u7528 onBackPressed() \u65b9\u6cd5\uff1f<\/ol>\n<pre class=\"post-pre\"><code>The onBackPressed() method is defined as shown below:\r\n\r\n```\r\n    @Override\r\n    public void onBackPressed() {\r\n        super.onBackPressed();\r\n    }\r\n```\r\n\r\nTo disable the back button and preventing it from destroying the current activity and going back we have to remove the line `super.onBackPressed();`\r\n<\/code><\/pre>\n<ol>\u4ec0\u4e48\u662fStateListDrawable\uff1f<\/ol>\n<pre class=\"post-pre\"><code>A StateListDrawable is a drawable object defined in the XML that allows us to show a different color\/background for a view for different states. Essentially it's used for Buttons to show a different look for each state(pressed, focused, selected, none).\r\n<\/code><\/pre>\n<ol>\u5b9e\u73b0\u4e00\u4e2a\u6309\u94ae\uff0c\u4f7f\u7528StateListDrawable\u6765\u8bbe\u5b9a\u6309\u94ae\u6309\u4e0b\u548c\u975e\u6309\u4e0b\u72b6\u6001\uff0c\u6309\u94ae\u5177\u6709\u5706\u89d2\u548c\u8fb9\u6846\u3002<\/ol>\n<pre class=\"post-pre\"><code>The selector drawable for a button is shown below.\r\n\r\n```\r\n&lt;selector xmlns:android=\"https:\/\/schemas.android.com\/apk\/res\/android\"&gt;\r\n\r\n&lt;item android:state_pressed=\"false\"&gt;\r\n \t&lt;shape android:shape=\"rectangle\"&gt;\r\n \t\t&lt;solid android:color=\"@android:color\/holo_red_dark\"\/&gt;\r\n \t\t&lt;stroke android:color=\"#000000\" android:width=\"3dp\"\/&gt;\r\n \t\t&lt;corners android:radius=\"2dp\"\/&gt;\r\n\t&lt;\/shape&gt;\r\n&lt;\/item&gt;\r\n\r\n&lt;item android:state_pressed=\"true\"&gt;\r\n\t&lt;shape android:shape=\"rectangle\"&gt;\r\n \t \t &lt;solid android:color=\"@android:color\/darker_gray\"\/&gt;\r\n \t \t &lt;stroke android:color=\"#FFFF\" android:width=\"1dp\"\/&gt;\r\n \t \t &lt;corners android:radius=\"2dp\"\/&gt;\r\n \t&lt;\/shape&gt;\r\n&lt;\/item&gt;\r\n\r\n&lt;\/selector&gt;\r\n```\r\n\r\nWe need to add this drawable XML in the android:background attribute of the button as:\r\n\r\n```\r\nandroid:background=\"@drawable\/btn_background\"\r\n```\r\n\r\nThe output looks like this: \r\n<\/code><\/pre>\n<ol>\u4ec0\u4e48\u662f\u7247\u6bb5\uff1f\u63cf\u8ff0\u7247\u6bb5\u7684\u751f\u547d\u5468\u671f\u65b9\u6cd5\u3002<\/ol>\n<pre class=\"post-pre\"><code>Fragments are a part of an activity and they contribute there own UI to the activity they are embedded in. A single activity can contain multiple fragments. Fragments are reusable across activities. The lifecycle methods of a Fragment are :\r\n\r\n1.  `onAttach(Activity)` : is called only once when it is attached with activity.\r\n2.  `onCreate(Bundle)` : it is used to initialise the fragment.\r\n3.  `onCreateView(LayoutInflater, ViewGroup, Bundle)` : creates and returns view hierarchy.\r\n4.  `onActivityCreated(Bundle)` : it is invoked after the completion of onCreate() method.\r\n5.  `onViewStateRestored(Bundle)` : it provides information to the fragment that all the saved state of fragment view hierarchy has been restored.\r\n6.  `onStart()` : makes the fragment visible.\r\n7.  `onResume()` : makes the fragment interactive.\r\n8.  `onPause()` : is called when fragment is no longer interactive.\r\n9.  `onStop()` : is called when fragment is no longer visible\r\n10.  `onDestroyView()` : it allows the fragment to clean up resources\r\n11.  `onDestroy()` : it allows the fragment to do final clean up of fragment state\r\n12.  `onDetach()` : it is called when the fragment is no longer associated with the activity\r\n\r\nAn image depicting the Fragments lifecycle is given below. \r\n<\/code><\/pre>\n<ol>\u5728\u70b9\u51fb\u6309\u94ae\u65f6\uff0c\u5982\u4f55\u901a\u8fc7\u7f16\u7a0b\u4ece\u53e6\u4e00\u4e2a\u6d3b\u52a8\u4e2d\u7ec8\u6b62\u6b63\u5728\u8fd0\u884c\u7684\u6d3b\u52a8\uff1f<\/ol>\n<pre class=\"post-pre\"><code>We'll declare and assign a class instance of the FirstActivity to itself as shown below.\r\n\r\n```\r\npublic class FirstActivity extends AppCompatActivity {\r\npublic static FirstActivity firstActivity;\r\n\r\n    @Override\r\n    protected void onCreate(Bundle savedInstanceState) {\r\n        super.onCreate(savedInstanceState);\r\n        setContentView(R.layout.activity_main);\r\n\r\n        firstActivity=this;\r\n}\r\n}\r\n```\r\n\r\nWe'll call finish() on the above instance of the FirstActivity to kill the activity from any other activity.\r\n\r\n```\r\nFirstActivity.firstActivity.finish()\r\n```\r\n<\/code><\/pre>\n<ol>\u4ec0\u4e48\u662fPendingIntent\uff1f<\/ol>\n<pre class=\"post-pre\"><code>A PendingIntent is a wrapper for the Intent object. It's passed to a foreign application (NotificationManager, AlarmManager) such that when some given conditions are met, the desired action is performed on the intent object it holds onto. The foreign application performs the intent with the set of permissions defined in our application.\r\n<\/code><\/pre>\n<ol>AsyncTask\u548cThread\u7c7b\u4e4b\u95f4\u6709\u4ec0\u4e48\u533a\u522b\uff1f<\/ol>\n<pre class=\"post-pre\"><code>A Thread is generally used for long tasks to be run in the background. We need a Handler class to use a Thread. An AsyncTask is an intelligent Thread subclass. It's recommended to use AsyncTask when the caller class is the UI Thread as there is no need to manipulate the handlers. AsyncTask is generally used for small tasks that can communicate back with the main UI thread using the two methods onPreExecute() and onPostExecute() it has. A Handler class is preferred when we need to perform a background task repeatedly after every x seconds\/minutes.\r\n<\/code><\/pre>\n<p>\u4e0b\u9762\u7ed9\u51fa\u4e86\u4e00\u4e2aAsyncTask\u7684\u793a\u4f8b\u3002<\/p>\n<pre class=\"post-pre\"><code>private class MyTask extends AsyncTask {\r\n      protected String doInBackground(String... params) {\r\n\r\n        Toast.makeText(getApplicationContext(),\"Will this work?\",Toast.LENGTH_LONG).show();\r\n\r\n          int count = 100;\r\n          int total = 0;\r\n          for (int i = 0; i &lt; count\/2; i++) {\r\n              total += i;\r\n          }\r\n          return String.valueOf(totalSize);\r\n      }\r\n\r\n      protected void onPostExecute(String result) {\r\n       \r\n      }\r\n }\r\n<\/code><\/pre>\n<ol>\u4ee5\u4e0a\u7684AsyncTask\u5982\u4f55\u4ece\u4e3b\u7ebf\u7a0b\u542f\u52a8\uff1f\u5b83\u80fd\u6210\u529f\u8fd0\u884c\u5417\uff1f<\/ol>\n<pre class=\"post-pre\"><code>We need to call the AsyncTask from the onCreate() using the following piece of code;\r\n\r\n```\r\nMyTask myTask= new MyTask();\r\nmyTask.execute();\r\n```\r\n\r\nNo. The application will crash with a runtime exception since we're updating the UI Thread by trying to display a Toast message inside the doInBackground method. We need to get rid of that line to run the application successfully.\r\n<\/code><\/pre>\n<ol>doInBackground\u65b9\u6cd5\u7684\u8fd4\u56de\u503c\u53bb\u54ea\u91cc\u4e86\uff1f\u5728onCreate()\u65b9\u6cd5\u4e2d\u5982\u4f55\u83b7\u53d6\u8fd9\u4e2a\u8fd4\u56de\u503c\uff1f<\/ol>\n<pre class=\"post-pre\"><code>The returned value of the doInBackground goes to the onPostExecute() method. We can update the main UI thread from here. To get the returned value in the onCreate() method we need to use the following code snippet.\r\n\r\n```\r\nMyTask myTask= new MyTask();\r\nString result=myTask.execute().get();\r\n```\r\n\r\nThis approach is not recommended as it blocks the main UI thread until the value is not returned. The ideal scenario to use it is when the other views of the UI thread need the value from the AsyncTask for processing.\r\n<\/code><\/pre>\n<ol>\u5b9e\u73b0\u4e00\u4e2a\u5f02\u6b65\u4efb\u52a1\uff0c\u5728\u7ed9\u5b9a\u7684\u65f6\u95f4\u95f4\u9694\u540e\u91cd\u590d\u6267\u884c\u3002<\/ol>\n<pre class=\"post-pre\"><code>We need to use a Handler class in the onPostExecute that executes the AsyncTask recursively.\r\n\r\n```\r\nprivate class MyTask extends AsyncTask {\r\n      protected String doInBackground(String... params) {\r\n\r\n        Toast.makeText(getApplicationContext(),\"Will this work?\",Toast.LENGTH_LONG).show();\r\n\r\n          int count = 100;\r\n          int total = 0;\r\n          for (int i = 0; i &lt; count\/2; i++) {\r\n              total += i;\r\n          }\r\n          return String.valueOf(totalSize);\r\n      }\r\n\r\n      protected void onPostExecute(String result) {\r\n\r\n\/\/ repeats after every 5 seconds here.\r\nnew Handler().postDelayed(new Runnable() {\r\n        @Override\r\n        public void run() {\r\n            new MyAsyncTask().execute(\"my String\");\r\n        }\r\n    }, 5*1000);       \r\n\r\n      }\r\n }\r\n```\r\n<\/code><\/pre>\n<ol>\u4ec0\u4e48\u662f\u670d\u52a1\uff1f<\/ol>\n<pre class=\"post-pre\"><code>A service is a component in android that's used for performing tasks in the background such as playing Music, location updating etc. Unlike activities, a service does not have a UI. Also, a service can keep running in the background even if the activity is destroyed.\r\n<\/code><\/pre>\n<ol>\u5982\u4f55\u542f\u52a8\/\u505c\u6b62\u4e00\u4e2a\u670d\u52a1\uff1f<\/ol>\n<pre class=\"post-pre\"><code>A service is started from an activity by executing the following code snippet.\r\n\r\n```\r\nstartService(new Intent(this, MyService.class));\r\n```\r\n\r\nThough just executing the above code won't start a service. We need to register the service first in the AndroidManifest.xml file as shown below.\r\n\r\n```\r\n&lt;service android:name=\"MyService\"\/&gt;\r\n```\r\n\r\nTo stop a service we execute `stopService()`. To stop the service from itself we call `stopSelf()`.\r\n<\/code><\/pre>\n<ol>\u5b9a\u4e49\u5e76\u533a\u5206\u8fd9\u4e24\u79cd\u670d\u52a1\u7684\u7c7b\u578b\u3002<\/ol>\n<pre class=\"post-pre\"><code>Services are largely divided into two categories : **Bound Services** and **Unbound\/Started Services**\r\n1.  **Bound Services**: An Android component may bind itself to a Service using `bindservice()`. A bound service would run as long as the other application components are bound to it. As soon as the components call `unbindService()`, the service destroys itself.\r\n2.  **Unbound Services**: A service is started when a component (like activity) calls startService() method and it runs in the background indefinitely even if the original component is destroyed.\r\n<\/code><\/pre>\n<ol>\u63cf\u8ff0\u4e00\u79cd\u670d\u52a1\u7684\u751f\u547d\u5468\u671f\u65b9\u6cd5\u3002<\/ol>\n<pre class=\"post-pre\"><code>-   `onStartCommand()` : This method is called when startService() is invoked. Once this method executes, the service is started and can run in the background indefinitely. This method is not needed if the service is defined as a bounded service. The service will run indefinitely in the background when this method is defined. We'll have a stop the service ourselves\r\n-   `onBind()` This method needs to be overridden when the service is defined as a bounded service. This method gets called when bindService() is invoked. In this method, we must provide an interface that clients use to communicate with the service, by returning an IBinder. We should always implement this method, but if you don\u2019t want to allow binding, then you should return null\r\n-   `onCreate()` : This method is called while the service is first created. Here all the service initialization is done\r\n-   `onDestroy()` : The system calls this method when the service is no longer used and is being destroyed. All the resources, receivers, listeners clean up are done here\r\n\r\n\r\n<\/code><\/pre>\n<ol>\u533a\u5206\u5e7f\u64ad\u63a5\u6536\u5668\u548c\u670d\u52a1\u3002<\/ol>\n<pre class=\"post-pre\"><code>A service is used for long running tasks in the background such as playing a music or tracking and updating the user's background location. A Broadcast Receiver is a component that once registered within an application executes the onReceive() method when some system event gets triggered. The events the receiver listens to are defined in the AndroidManifest.xml in the intent filters. Types of system events that a Broadcast Receiver listens to are: changes in the network, boot completed, battery low, push notifications received etc. We can even send our own custom broadcasts using `sendBroadcast(intent)`.\r\n<\/code><\/pre>\n<ol>Broadcast Receiver\u5728manifest.xml\u4e2d\u5982\u4f55\u6ce8\u518c\uff1f<\/ol>\n<pre class=\"post-pre\"><code>The Broadcast Receiver is defined inside the receiver tags with the necessary actions defined inside the intent filter as shown below.\r\n\r\n```\r\n&lt;receiver android:name=\".ConnectionReceiver\" &gt;\r\n\t&lt;intent-filter&gt;\r\n\t\t&lt;action android:name=\"android.net.conn.CONNECTIVITY_CHANGE\" \/&gt;\r\n\t&lt;\/intent-filter&gt;\r\n&lt;\/receiver&gt;\r\n```\r\n<\/code><\/pre>\n<ol>RecyclerView\u548cListView\u6709\u4ec0\u4e48\u4e0d\u540c\u4e4b\u5904\uff1f<\/ol>\n<pre class=\"post-pre\"><code>-   A RecyclerView recycles and reuses cells when scrolling. This is a default behaviour. It's possible to implement the same in a ListView too but we need to implement a ViewHolder there\r\n-   A RecyclerView decouples list from its container so we can put list items easily at run time in the different containers (linearLayout, gridLayout) by setting LayoutManager\r\n-   Animations of RecyclerView items are decoupled and delegated to `ItemAnimator`\r\n<\/code><\/pre>\n<ol>\u5728ExpandableListView\u4e2d\u5b9e\u73b0\u6240\u6709\u7684\u5934\u90e8\u7ec4\u9ed8\u8ba4\u90fd\u5c55\u5f00\u3002<\/ol>\n<pre class=\"post-pre\"><code>We need to call the method expandGroup on the adapter to keep all the group headers as expanded.\r\n\r\n```\r\nExpandableListView el = (ExpandableListView) findViewById(R.id.el_main);\r\nelv.setAdapter(adapter);\r\nfor(int i=0; i &lt; adapter.getGroupCount(); i++)\r\n    el.expandGroup(i);\r\n```\r\n<\/code><\/pre>\n<ol>\u5f53\u6267\u884c\u5f02\u6b65\u4efb\u52a1\u7684\u6d3b\u52a8\u6539\u53d8\u65b9\u5411\u65f6\uff0cAsyncTask\u4f1a\u53d1\u751f\u4ec0\u4e48\u53d8\u5316\uff1f<\/ol>\n<pre class=\"post-pre\"><code>The lifecycle of an AsyncTask is not tied onto the Activity since it's occurring on a background thread. Hence an orientation change won't stop the AsyncTask. But if the AsyncTask tries to update the UI thread after the orientation is changed, it would give rise to `java.lang.IllegalArgumentException: View not attached to window manager` since it will try to update the former instances of the activity that got reset.\r\n<\/code><\/pre>\n<ol>\/assets\u548c\/res\/raw\/\u6587\u4ef6\u5939\u6709\u4ec0\u4e48\u7528\u9014\uff1f<\/ol>\n<pre class=\"post-pre\"><code>**\/assets** folder is empty by default. We can place files such as custom fonts, game data here. Also, this folder is ideal for maintaining a custom dictionary for lookup. The original file name is preserved. These files are accessible using the AssetManager (**getAssets()**). **\/res\/raw** folder is used to store xml files, and files like \\*.mp3, \\*.ogg etc. This folder gets built using aapt and the files are accessible using R.raw.\r\n<\/code><\/pre>\n<p>\u8fd9\u5c31\u662f\u6240\u6709\u5173\u4e8e\u5b89\u5353\u9762\u8bd5\u95ee\u9898\u548c\u7b54\u6848\u7684\u5185\u5bb9\u3002\u5982\u679c\u6211\u6536\u5230\u66f4\u591a\u7684\u5b89\u5353\u9762\u8bd5\u95ee\u9898\uff0c\u6211\u4f1a\u5c06\u5b83\u4eec\u548c\u8be6\u7ec6\u7b54\u6848\u52a0\u5165\u5230\u5217\u8868\u4e2d\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Android\u662f\u624b\u673a\u4e0a\u6700\u53d7\u6b22\u8fce\u7684\u64cd\u4f5c\u7cfb\u7edf\u3002\u5982\u4ecaAndroid\u5e94\u7528\u975e\u5e38\u6d41\u884c\u3002\u7531\u4e8eAndroid\u662f\u5f00\u6e90\u7684\uff0c\u56e0\u6b64\u975e\u5e38 [&hellip;]<\/p>\n","protected":false},"author":11,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[1922,900,1921,1640,1592],"class_list":{"0":"post-695","1":"post","2":"type-post","3":"status-publish","4":"format-standard","5":"hentry","6":"category-uncategorized","7":"tag-android","10":"tag-1640","11":"tag-1592"},"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v21.5 (Yoast SEO v21.5) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>2023\u6700\u65b0Android\u9762\u8bd5\u95ee\u9898\u4e0e\u56de\u7b54\u5927\u5168\uff1a\u9762\u8bd5\u5b98\u6700\u7231\u95ee\u768450\u9053\u9898\u8be6\u89e3 - Blog - Silicon Cloud<\/title>\n<meta name=\"description\" content=\"\u6574\u74062023\u5e74\u6700\u65b0Android\u9762\u8bd5\u95ee\u9898\u4e0e\u6807\u51c6\u56de\u7b54\uff0c\u6db5\u76d6Java\u57fa\u7840\u3001Android\u7ec4\u4ef6\u3001\u6027\u80fd\u4f18\u5316\u7b49\u6838\u5fc3\u77e5\u8bc6\u70b9\u3002\u5305\u542b\u9762\u8bd5\u5b98\u6700\u7231\u95ee\u768450\u9053\u9ad8\u9891\u9898\u8be6\u89e3\uff0c\u52a9\u4f60\u8f7b\u677e\u5e94\u5bf9Android\u5f00\u53d1\u5de5\u7a0b\u5e08\u6280\u672f\u9762\u8bd5\uff0c\u63d0\u9ad8\u9762\u8bd5\u6210\u529f\u7387\u3002\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.silicloud.com\/zh\/blog\/android\u9762\u8bd5\u95ee\u9898\u4e0e\u56de\u7b54\/\" \/>\n<meta property=\"og:locale\" content=\"zh_CN\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"2023\u6700\u65b0Android\u9762\u8bd5\u95ee\u9898\u4e0e\u56de\u7b54\u5927\u5168\uff1a\u9762\u8bd5\u5b98\u6700\u7231\u95ee\u768450\u9053\u9898\u8be6\u89e3\" \/>\n<meta property=\"og:description\" content=\"\u6574\u74062023\u5e74\u6700\u65b0Android\u9762\u8bd5\u95ee\u9898\u4e0e\u6807\u51c6\u56de\u7b54\uff0c\u6db5\u76d6Java\u57fa\u7840\u3001Android\u7ec4\u4ef6\u3001\u6027\u80fd\u4f18\u5316\u7b49\u6838\u5fc3\u77e5\u8bc6\u70b9\u3002\u5305\u542b\u9762\u8bd5\u5b98\u6700\u7231\u95ee\u768450\u9053\u9ad8\u9891\u9898\u8be6\u89e3\uff0c\u52a9\u4f60\u8f7b\u677e\u5e94\u5bf9Android\u5f00\u53d1\u5de5\u7a0b\u5e08\u6280\u672f\u9762\u8bd5\uff0c\u63d0\u9ad8\u9762\u8bd5\u6210\u529f\u7387\u3002\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.silicloud.com\/zh\/blog\/android\u9762\u8bd5\u95ee\u9898\u4e0e\u56de\u7b54\/\" \/>\n<meta property=\"og:site_name\" content=\"Blog - Silicon Cloud\" \/>\n<meta property=\"article:published_time\" content=\"2022-09-09T14:49:08+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-08-02T19:29:23+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/65647fd4a4b2f92e6c72df8e\/2-0.jpg\" \/>\n<meta name=\"author\" content=\"\u65b0, \u97f5\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u4f5c\u8005\" \/>\n\t<meta name=\"twitter:data1\" content=\"\u65b0, \u97f5\" \/>\n\t<meta name=\"twitter:label2\" content=\"\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4\" \/>\n\t<meta name=\"twitter:data2\" content=\"1 \u5206\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/android%e9%9d%a2%e8%af%95%e9%97%ae%e9%a2%98%e4%b8%8e%e5%9b%9e%e7%ad%94\/\",\"url\":\"https:\/\/www.silicloud.com\/zh\/blog\/android%e9%9d%a2%e8%af%95%e9%97%ae%e9%a2%98%e4%b8%8e%e5%9b%9e%e7%ad%94\/\",\"name\":\"2023\u6700\u65b0Android\u9762\u8bd5\u95ee\u9898\u4e0e\u56de\u7b54\u5927\u5168\uff1a\u9762\u8bd5\u5b98\u6700\u7231\u95ee\u768450\u9053\u9898\u8be6\u89e3 - Blog - Silicon Cloud\",\"isPartOf\":{\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#website\"},\"datePublished\":\"2022-09-09T14:49:08+00:00\",\"dateModified\":\"2025-08-02T19:29:23+00:00\",\"author\":{\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/4ba4019495123db3038fd0809e6959c9\"},\"description\":\"\u6574\u74062023\u5e74\u6700\u65b0Android\u9762\u8bd5\u95ee\u9898\u4e0e\u6807\u51c6\u56de\u7b54\uff0c\u6db5\u76d6Java\u57fa\u7840\u3001Android\u7ec4\u4ef6\u3001\u6027\u80fd\u4f18\u5316\u7b49\u6838\u5fc3\u77e5\u8bc6\u70b9\u3002\u5305\u542b\u9762\u8bd5\u5b98\u6700\u7231\u95ee\u768450\u9053\u9ad8\u9891\u9898\u8be6\u89e3\uff0c\u52a9\u4f60\u8f7b\u677e\u5e94\u5bf9Android\u5f00\u53d1\u5de5\u7a0b\u5e08\u6280\u672f\u9762\u8bd5\uff0c\u63d0\u9ad8\u9762\u8bd5\u6210\u529f\u7387\u3002\",\"breadcrumb\":{\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/android%e9%9d%a2%e8%af%95%e9%97%ae%e9%a2%98%e4%b8%8e%e5%9b%9e%e7%ad%94\/#breadcrumb\"},\"inLanguage\":\"zh-Hans\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.silicloud.com\/zh\/blog\/android%e9%9d%a2%e8%af%95%e9%97%ae%e9%a2%98%e4%b8%8e%e5%9b%9e%e7%ad%94\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/android%e9%9d%a2%e8%af%95%e9%97%ae%e9%a2%98%e4%b8%8e%e5%9b%9e%e7%ad%94\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"\u9996\u9875\",\"item\":\"https:\/\/www.silicloud.com\/zh\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"2023\u6700\u65b0Android\u9762\u8bd5\u95ee\u9898\u4e0e\u56de\u7b54\u5927\u5168\uff1a\u9762\u8bd5\u5b98\u6700\u7231\u95ee\u768450\u9053\u9898\u8be6\u89e3\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#website\",\"url\":\"https:\/\/www.silicloud.com\/zh\/blog\/\",\"name\":\"Blog - Silicon Cloud\",\"description\":\"\",\"inLanguage\":\"zh-Hans\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/4ba4019495123db3038fd0809e6959c9\",\"name\":\"\u65b0, \u97f5\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-Hans\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/d484b6c6e4ae82e8a9efea989e1d2af46d9b6ef128101e63b18f559fca0ae627?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/d484b6c6e4ae82e8a9efea989e1d2af46d9b6ef128101e63b18f559fca0ae627?s=96&d=mm&r=g\",\"caption\":\"\u65b0, \u97f5\"},\"url\":\"https:\/\/www.silicloud.com\/zh\/blog\/author\/yunxin\/\"},{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-Hans\",\"@id\":\"https:\/\/www.silicloud.com\/zh\/blog\/android%e9%9d%a2%e8%af%95%e9%97%ae%e9%a2%98%e4%b8%8e%e5%9b%9e%e7%ad%94\/#local-main-organization-logo\",\"url\":\"\",\"contentUrl\":\"\",\"caption\":\"Blog - Silicon Cloud\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"2023\u6700\u65b0Android\u9762\u8bd5\u95ee\u9898\u4e0e\u56de\u7b54\u5927\u5168\uff1a\u9762\u8bd5\u5b98\u6700\u7231\u95ee\u768450\u9053\u9898\u8be6\u89e3 - Blog - Silicon Cloud","description":"\u6574\u74062023\u5e74\u6700\u65b0Android\u9762\u8bd5\u95ee\u9898\u4e0e\u6807\u51c6\u56de\u7b54\uff0c\u6db5\u76d6Java\u57fa\u7840\u3001Android\u7ec4\u4ef6\u3001\u6027\u80fd\u4f18\u5316\u7b49\u6838\u5fc3\u77e5\u8bc6\u70b9\u3002\u5305\u542b\u9762\u8bd5\u5b98\u6700\u7231\u95ee\u768450\u9053\u9ad8\u9891\u9898\u8be6\u89e3\uff0c\u52a9\u4f60\u8f7b\u677e\u5e94\u5bf9Android\u5f00\u53d1\u5de5\u7a0b\u5e08\u6280\u672f\u9762\u8bd5\uff0c\u63d0\u9ad8\u9762\u8bd5\u6210\u529f\u7387\u3002","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.silicloud.com\/zh\/blog\/android\u9762\u8bd5\u95ee\u9898\u4e0e\u56de\u7b54\/","og_locale":"zh_CN","og_type":"article","og_title":"2023\u6700\u65b0Android\u9762\u8bd5\u95ee\u9898\u4e0e\u56de\u7b54\u5927\u5168\uff1a\u9762\u8bd5\u5b98\u6700\u7231\u95ee\u768450\u9053\u9898\u8be6\u89e3","og_description":"\u6574\u74062023\u5e74\u6700\u65b0Android\u9762\u8bd5\u95ee\u9898\u4e0e\u6807\u51c6\u56de\u7b54\uff0c\u6db5\u76d6Java\u57fa\u7840\u3001Android\u7ec4\u4ef6\u3001\u6027\u80fd\u4f18\u5316\u7b49\u6838\u5fc3\u77e5\u8bc6\u70b9\u3002\u5305\u542b\u9762\u8bd5\u5b98\u6700\u7231\u95ee\u768450\u9053\u9ad8\u9891\u9898\u8be6\u89e3\uff0c\u52a9\u4f60\u8f7b\u677e\u5e94\u5bf9Android\u5f00\u53d1\u5de5\u7a0b\u5e08\u6280\u672f\u9762\u8bd5\uff0c\u63d0\u9ad8\u9762\u8bd5\u6210\u529f\u7387\u3002","og_url":"https:\/\/www.silicloud.com\/zh\/blog\/android\u9762\u8bd5\u95ee\u9898\u4e0e\u56de\u7b54\/","og_site_name":"Blog - Silicon Cloud","article_published_time":"2022-09-09T14:49:08+00:00","article_modified_time":"2025-08-02T19:29:23+00:00","og_image":[{"url":"https:\/\/cdn.silicloud.com\/blog-img\/blog\/img\/65647fd4a4b2f92e6c72df8e\/2-0.jpg"}],"author":"\u65b0, \u97f5","twitter_card":"summary_large_image","twitter_misc":{"\u4f5c\u8005":"\u65b0, \u97f5","\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4":"1 \u5206"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.silicloud.com\/zh\/blog\/android%e9%9d%a2%e8%af%95%e9%97%ae%e9%a2%98%e4%b8%8e%e5%9b%9e%e7%ad%94\/","url":"https:\/\/www.silicloud.com\/zh\/blog\/android%e9%9d%a2%e8%af%95%e9%97%ae%e9%a2%98%e4%b8%8e%e5%9b%9e%e7%ad%94\/","name":"2023\u6700\u65b0Android\u9762\u8bd5\u95ee\u9898\u4e0e\u56de\u7b54\u5927\u5168\uff1a\u9762\u8bd5\u5b98\u6700\u7231\u95ee\u768450\u9053\u9898\u8be6\u89e3 - Blog - Silicon Cloud","isPartOf":{"@id":"https:\/\/www.silicloud.com\/zh\/blog\/#website"},"datePublished":"2022-09-09T14:49:08+00:00","dateModified":"2025-08-02T19:29:23+00:00","author":{"@id":"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/4ba4019495123db3038fd0809e6959c9"},"description":"\u6574\u74062023\u5e74\u6700\u65b0Android\u9762\u8bd5\u95ee\u9898\u4e0e\u6807\u51c6\u56de\u7b54\uff0c\u6db5\u76d6Java\u57fa\u7840\u3001Android\u7ec4\u4ef6\u3001\u6027\u80fd\u4f18\u5316\u7b49\u6838\u5fc3\u77e5\u8bc6\u70b9\u3002\u5305\u542b\u9762\u8bd5\u5b98\u6700\u7231\u95ee\u768450\u9053\u9ad8\u9891\u9898\u8be6\u89e3\uff0c\u52a9\u4f60\u8f7b\u677e\u5e94\u5bf9Android\u5f00\u53d1\u5de5\u7a0b\u5e08\u6280\u672f\u9762\u8bd5\uff0c\u63d0\u9ad8\u9762\u8bd5\u6210\u529f\u7387\u3002","breadcrumb":{"@id":"https:\/\/www.silicloud.com\/zh\/blog\/android%e9%9d%a2%e8%af%95%e9%97%ae%e9%a2%98%e4%b8%8e%e5%9b%9e%e7%ad%94\/#breadcrumb"},"inLanguage":"zh-Hans","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.silicloud.com\/zh\/blog\/android%e9%9d%a2%e8%af%95%e9%97%ae%e9%a2%98%e4%b8%8e%e5%9b%9e%e7%ad%94\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.silicloud.com\/zh\/blog\/android%e9%9d%a2%e8%af%95%e9%97%ae%e9%a2%98%e4%b8%8e%e5%9b%9e%e7%ad%94\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"\u9996\u9875","item":"https:\/\/www.silicloud.com\/zh\/blog\/"},{"@type":"ListItem","position":2,"name":"2023\u6700\u65b0Android\u9762\u8bd5\u95ee\u9898\u4e0e\u56de\u7b54\u5927\u5168\uff1a\u9762\u8bd5\u5b98\u6700\u7231\u95ee\u768450\u9053\u9898\u8be6\u89e3"}]},{"@type":"WebSite","@id":"https:\/\/www.silicloud.com\/zh\/blog\/#website","url":"https:\/\/www.silicloud.com\/zh\/blog\/","name":"Blog - Silicon Cloud","description":"","inLanguage":"zh-Hans"},{"@type":"Person","@id":"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/4ba4019495123db3038fd0809e6959c9","name":"\u65b0, \u97f5","image":{"@type":"ImageObject","inLanguage":"zh-Hans","@id":"https:\/\/www.silicloud.com\/zh\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/d484b6c6e4ae82e8a9efea989e1d2af46d9b6ef128101e63b18f559fca0ae627?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/d484b6c6e4ae82e8a9efea989e1d2af46d9b6ef128101e63b18f559fca0ae627?s=96&d=mm&r=g","caption":"\u65b0, \u97f5"},"url":"https:\/\/www.silicloud.com\/zh\/blog\/author\/yunxin\/"},{"@type":"ImageObject","inLanguage":"zh-Hans","@id":"https:\/\/www.silicloud.com\/zh\/blog\/android%e9%9d%a2%e8%af%95%e9%97%ae%e9%a2%98%e4%b8%8e%e5%9b%9e%e7%ad%94\/#local-main-organization-logo","url":"","contentUrl":"","caption":"Blog - Silicon Cloud"}]}},"_links":{"self":[{"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/posts\/695","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/users\/11"}],"replies":[{"embeddable":true,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/comments?post=695"}],"version-history":[{"count":4,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/posts\/695\/revisions"}],"predecessor-version":[{"id":110513,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/posts\/695\/revisions\/110513"}],"wp:attachment":[{"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/media?parent=695"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/categories?post=695"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.silicloud.com\/zh\/blog\/wp-json\/wp\/v2\/tags?post=695"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}