高级程序员修炼之道-Android培训系列课程之Thread
aardio thread用法
aardio thread用法一、概述Thread是Aardio提供的一种多线程处理机制,用于在Aardio程序中实现并发执行。
使用Thread可以提高程序的执行效率,同时避免阻塞主线程,提高用户体验。
二、创建Thread要使用Thread,首先需要创建一个Thread对象。
在Aardio中,可以使用Thread类的构造函数来创建Thread对象。
例如:Thread thread = new Thread(new Runnable() {@Overridepublic void run() {// 线程执行的代码}});三、启动Thread创建Thread对象后,需要调用其start()方法来启动线程。
这将使线程进入可执行状态,但并不会立即执行。
要使线程真正执行,需要将执行权交给操作系统。
在Aardio中,可以使用AardioApp类的run()方法来将执行权交给操作系统,并开始执行Thread中的代码。
例如:app.run();四、线程同步在使用Thread时,需要注意线程同步问题。
多个线程同时访问共享资源时,可能会导致数据竞争和不一致性。
为了解决这个问题,可以使用synchronized关键字对共享资源进行加锁,以实现线程同步。
例如:synchronized(object) {// 共享资源的访问代码}其中,object是用于锁定的对象。
只有持有该对象的锁的线程才能进入同步块中访问共享资源。
五、线程池在实际应用中,频繁地创建和销毁线程会占用大量的系统资源,影响程序的性能。
为了解决这个问题,可以使用线程池来管理线程。
Aardio提供了ThreadPool类来实现线程池功能。
使用ThreadPool类,可以方便地创建和管理线程池,提高程序的性能和稳定性。
六、中断线程在某些情况下,可能需要中断正在执行的线程。
在Aardio中,可以使用Thread类的interrupt()方法来中断线程。
被中断的线程将收到中断通知,并可以处理该中断。
Android进阶——多线程系列之Thread、Runnable、Callable、Future、FutureTask
Android进阶——多线程系列之Thread、Runnable、Callable、Future、FutureTask前言多线程一直是初学者最抵触的东西,如果你想进阶的话,那必须闯过这道难关,特别是多线程中Thread、Runnable、Callable、Future、FutureTask这几个类往往是初学者容易搞混的。
这里先总结这几个类特点和区别,让大家带着模糊印象来学习这篇文章Thread、Runnable、Callable:都是线程Thread特点:提供了线程等待、线程睡眠、线程礼让等操作Runnable和Callable特点:都是接口,并提供对应的实现方法Runnable、Callable区别:Runnable无返回值,Callable有返回值Future:提供了对Runnable和Callable任务的执行结果进行取消、查询是否完成、获取结果、设置结果等操作FutureTask:Runnable和Future的结合体,即拥有Future的特性Thread和Runnable的关系我们对线程的使用,经常有这两种写法new Thread(new Runnable() {@Overridepublic void run() {//子线程操作}}).start();new Thread(){@Overridepublic void run() {//子线程操作}}.start();这也就是我们要讲的Thread和Runnable的关系,其实它们是一样的,都是线程,最终启动线程后都会执行run()方法里面的内容,具体是怎么一回事,让我们从Thread的源码开始分析class Thread implements Runnable {private Runnable target;//构造函数public Thread(ThreadGroup group, Runnable target) {init(group, target, "Thread-" + nextThreadNum(), 0);}//继续追踪init()方法private void init(ThreadGroup g, Runnable target, String name, long stackSize) { Thread parent = currentThread();if (g == null) {g = parent.getThreadGroup();}g.addUnstarted();this.group = g;this.target = target;this.priority = parent.getPriority();this.daemon = parent.isDaemon();setName(name);init2(parent);/* Stash the specified stack size in case the VM cares */this.stackSize = stackSize;tid = nextThreadID();}}可以看到Thread就是实现Runnable的,所以Thread也可以说是Runnable,它俩就像亲生兄弟一样。
高级程序员修炼之道-Android培训系列课程之ContentProvider9
ContentProviderContentProvider URI ContentResolver URI code.db ContentProvider ContentResolver URIContentProvider 1URI ContentProvider SQLite2 code.db URISQLite2 ContryCode.java JAR1.package com.studio.android.chp9.ex3;2.3.import .Uri;4.5.public class CountryCode {6.7.public static final String DB_NAME = "code.db";8.public static final String TB_NAME = "countrycode";9.public static final int VERSION = 1;10.11.public static final String ID = "_id";12.public static final String COUNTRY = "country";13.public static final String CODE = "code";14.15.public static final String AUTHORITY =16."com.studio.andriod.provider.countrycode";17.public static final int ITEM = 1;18.public static final int ITEM_ID = 2;19.20.public static final String CONTENT_TYPE =21."vnd.android.cursor.dir/vnd.studio.android.countrycode";22.public static final String CONTENT_ITEM_TYPE =23."vnd.android.cursor.item/vnd.studio.android.countrycode";24.25.public static final Uri CONTENT_URI =26.Uri.parse("content://" + AUTHORITY + "/item");27.}DB_NAME TB_NAME VERSION ID COUNTRY CODE AUTHORITY ContentProvider ITEM ITEM_ID UriMatcher item item/id CONTENT_TYPE CONTENT_ITEM_TYPE MIME MIME vnd.android.cursor.item/ MIME vnd.android.cursor.dir/ CONTENT_URI content:// URISQLite2 ContentProvider MyProvider.java MyHelper SQLiteDatabaseContext.OpenOrCreate()1.public class MyProvider extends ContentProvider {2.MyHelper dbHelper;3.private static final UriMatcher sMatcher;4.static {5.sMatcher = new UriMatcher(UriMatcher.NO_MATCH);6.sMatcher.addURI(CountryCode.AUTHORITY,7."item",CountryCode.ITEM);8.sMatcher.addURI(CountryCode.AUTHORITY,9."item/#", CountryCode.ITEM_ID);10.}11....12.}UriMatcher ContentProvider Uri match() -1 UriMatcher.NO_MATCH addURI() URIContentProvider AUTHORITY # * match() URIContentProvider 61.@Override2.public boolean onCreate() {3.dbHelper = new MyHelper(getContext(), CountryCode.DB_NAME,4.null,CountryCode.VERSION);5.return true;6.}ContentProvider onCreate() ContentProvider true false ContentProvider1.@Override2.public String getType(Uri uri) {3.switch (sMatcher.match(uri)) {4.case CountryCode.ITEM:5.return CountryCode.CONTENT_TYPE;6.case CountryCode.ITEM_ID:7.return CountryCode.CONTENT_ITEM_TYPE;8.default:9.throw new IllegalArgumentException("Unknown URI " + uri);10.}11.}getTyper() MIME sMatcher URI MIME URI IllegalArgumentException1.@Override2.p ublic int delete(Uri uri, String where, String[] args) {3.S QLiteDatabase db = dbHelper.getWritableDatabase();4.i nt count;5.s witch (sMatcher.match(uri)) {6.c ase CountryCode.ITEM:7.c ount = db.delete(CountryCode.TB_NAME, where,args);8.b reak;9.c ase CountryCode.ITEM_ID:10.String id = uri.getPathSegments().get(1);11.count = db.delete(CountryCode.TB_NAME, CountryCode.ID + "=" + id12.+ (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), args);13.break;14.default:15.throw new IllegalArgumentException("Unknown URI " + uri);16.}17.getContext().getContentResolver().notifyChange(uri, null);18.return count;19.}20.@Override21.public int update(Uri uri, ContentValues values,22.String where, String[] args) {23.SQLiteDatabase db = dbHelper.getWritableDatabase();24.int count;25.switch (sMatcher.match(uri)) {26.case CountryCode.ITEM:27.count = db.update(CountryCode.TB_NAME,values, where,args);28.break;29.case CountryCode.ITEM_ID:30.String id = uri.getPathSegments().get(1);31.count = db.update(CountryCode.TB_NAME,values,CountryCode.ID+"=" + id32.+ (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), args);33.break;34.default:35.throw new IllegalArgumentException("Unknown URI " + uri);36.}37.getContext().getContentResolver().notifyChange(uri, null);38.return count;39.}delete() update() SQLiteDatabase Uri sMatcher SQLiteDatabase where getContext() update() ContextContext ContentResolver notifyChange() URI observer1.@Override2.public Uri insert(Uri uri, ContentValues initialValues) {3.SQLiteDatabase db = dbHelper.getWritableDatabase();4.long rowId;5.if (sMatcher.match(uri) != CountryCode.ITEM) {6.throw new IllegalArgumentException("Unknown URI " + uri);7.}8.rowId =9.db.insert(CountryCode.TB_NAME,CountryCode.ID,initialValues);10.if (rowId > 0) {11.Uri noteUri =12.ContentUris.withAppendedId(CountryCode.CONTENT_URI, rowId);13.getContext().getContentResolver().notifyChange(noteUri, null);14.return noteUri;15.}16.throw new SQLException("Failed to insert row into " + uri);17.}insert() URI URI URI SQLiteDatabase insert() URI1.public Cursor query(Uri uri, String[] projection,2.String selection, String[] args,String order) {3.SQLiteDatabase db = dbHelper.getReadableDatabase();4.Cursor c;5.switch (sMatcher.match(uri)) {6.case CountryCode.ITEM:7. c = db.query(CountryCode.TB_NAME, projection, selection,8.args,null,null,order);9.break;10.case CountryCode.ITEM_ID:11.String id = uri.getPathSegments().get(1);12.c = db.query(CountryCode.TB_NAME, projection, CountryCode.ID + "="13.+ id14.+ (!TextUtils.isEmpty(selection)15.? " AND (" + selection + ')' : ""),16.args,null,null,order);17.break;18.default:19.throw new IllegalArgumentException("Unknown URI " + uri);20.}21.c.setNotificationUri(getContext().getContentResolver(), uri);22.return c;23.}query() Cursor SQLiteDatabase sMatcher URI URI where setNotificationUri() Cursor URIContentProvider Android-Manifest.xml ContentProvider AndroidManifest.xml<provider android:name="MyProvider"android:authorities="com.studio.andriod.provider.countrycode"/>android:name ContentProvider android:authorities content:// URI ContentProvider android:readPermission android:writePermission ContentProvider onCreate() setRead-Permission() setWritePermission()ContentProvider JAR CountryCode JAR(1) CountryCode.java Export...(2) JAR file Next(3) CountryCode.java Browse... workspace Finish CountryCode.jarJAR Build path Add External Archive 9-5 JAR importContentProvider Android SDK ContentProvider Android AndroidManifest.XMLContentResolver ContentProvider “ ” AndroidManifest.XML ContentProvider multiprocess Android ContentResolver notifyChange() ContentObserver ContentResolver register unregisterContentProvider ContentProvider 2 ContentProvider ContentProvider Content provider。
高级程序员修炼之道-Android培训系列课程之Service3
儈㓗〻ᒿઈ⛬؞ѻ䚃-Android ษ䇝㌫ࡇ䈮〻ѻ Service
android SDK ᨀҶ Serviceˈ⭘Ҿ㊫լ*nix ᆸᣔ䘋〻ᡆ㘵 windows Ⲵᴽ࣑DŽ
Service ᴹє㊫ර˖
1. ᵜൠᴽ࣑˄Local Service˅˖⭘Ҿᓄ⭘〻ᒿ䜘 2. 䘌〻ᴽ࣑˄Remote Sercie˅˖⭘Ҿ android ㌫㔏䜘Ⲵᓄ⭘〻ᒿѻ䰤
} } }).start(); }
@Override public void onDestroy() {
super.onDestroy(); this.threadDisable = true; Log.v("CountService", "on destroy"); }
/* (non-Javadoc) * @see com.easymorse.ICountService#getCount() */ public int getCount() {
ਟ䙊䗷ᰕᘇḕⴻࡠਾਠ㓯〻ᢃঠⲴ䇑ᮠᇩDŽ
㕆߉ᵜൠᴽ઼࣑ Activity ӔӂⲴ皮ֻ
к䶒Ⲵ皮ֻᱟ䙊䗷 startService ઼ stopService ࣘޣ䰝ᴽ࣑ⲴDŽ䘲⭘Ҿᴽ઼࣑ activity ѻ䰤⋑ᴹ䈳⭘ӔӂⲴᛵߥDŽྲ᷌ѻ䰤䴰㾱Ր䙂৲ᮠᡆ㘵ᯩ⌅䈳⭘DŽ䴰㾱֯⭘ bind ઼ unbind ᯩ ⌅DŽ
程序员修炼之道读后感
程序员修炼之道读后感在这个数字化的时代,代码如同魔法,而程序员就是挥舞着魔法棒的巫师。
最近读了《程序员修炼之道》这本书,就像在代码的迷宫里找到了一盏明灯。
书中提到的很多观点和方法,让我这个在编程世界里摸爬滚打的人有了新的感悟。
比如说,关于代码的可读性和可维护性,这可不是一个小问题。
以前,我总是想着怎么快速把功能实现,代码写得那叫一个随心所欲,只有我自己能看懂。
结果呢,过了一段时间再回头看,我都得挠着头琢磨半天,更别提让别人接手了。
这就好像给自己挖了个坑,然后还得费劲地往外爬。
还有关于如何应对变化,这可太重要了。
在实际工作中,需求变更是家常便饭。
有时候客户上午说要这样,下午又改成那样了。
要是没有做好应对变化的准备,那可真是要手忙脚乱。
但给我印象最深的,还是书中强调的注重细节和持续学习。
就拿我前段时间做的一个项目来说吧。
那是一个为一家小型企业开发的客户管理系统,听起来好像不是特别复杂,对吧?但真做起来,才发现到处都是“坑”。
一开始,我按照常规的思路,设计好了数据库结构,写好了主要的功能模块。
一切看起来都挺顺利的,我还暗自得意,觉得这次能轻松搞定。
然而,当我开始进行测试的时候,问题就一个接一个地冒出来了。
比如说,在输入客户姓名的时候,如果用户不小心输入了一些特殊字符,系统就直接崩溃了。
这可把我给急坏了,赶紧去检查代码,发现我在处理输入数据的时候,根本就没有考虑到这种情况,这就是典型的细节没处理好。
于是,我开始重新审视整个代码,对输入数据的处理进行了全面的优化。
不仅要检查特殊字符,还要对数据的长度、格式等进行严格的验证。
这一番折腾下来,可花费了我不少的时间和精力。
但这还只是个开始。
在系统上线之后,用户又提出了一些新的需求。
比如他们希望能够按照客户的消费金额进行排序,并且能够导出相关的数据。
这可让我有点头疼了,因为最初的设计并没有考虑到这些功能。
没办法,只能硬着头皮改。
这个过程中,我又发现了之前代码中的一些不合理的地方,比如一些函数的命名不够清晰,导致我在修改的时候都搞不清楚它们的具体作用。
thread的构造方法
thread的构造方法Thread类是Java中用于创建和管理多线程的类,它提供了一些方法来控制线程的生命周期和执行过程。
Thread类有多个构造方法可以使用,我们将详细介绍每个构造方法的功能和用法。
1. Thread(:这是Thread类的默认构造方法,创建一个新的线程对象。
使用这个构造方法创建的线程没有指定线程名和要执行的任务。
2. Thread(Runnable target):这个构造方法是最常用的构造方法之一、它接受一个Runnable接口实现类作为参数,用于指定要执行的任务。
可以通过重写Runnable接口的run(方法来定义线程的具体逻辑。
3. Thread(Runnable target, String name):这个构造方法与上一个构造方法类似,不同之处在于可以指定线程的名称。
线程名称可以帮助我们更好地识别不同的线程,方便线程的管理和调试。
4. Thread(String name):这个构造方法只指定了线程的名称,没有指定要执行的任务。
可以通过继承Thread类并重写其run(方法来定义线程的逻辑。
5. Thread(ThreadGroup group, Runnable target):这个构造方法指定了线程所属的线程组,以及要执行的任务。
线程组用于将多个线程组织起来,可以方便地对它们进行管理和控制。
6. Thread(ThreadGroup group, Runnable target, String name):这个构造方法与上一个构造方法类似,不同之处在于可以指定线程的名称。
7. Thread(ThreadGroup group, Runnable target, String name, long stackSize):这个构造方法与前面的构造方法类似,不同之处在于可以指定线程的堆栈大小。
堆栈大小表示线程执行时所分配的内存空间。
除了以上列出的常用构造方法,Thread类还提供了一些其他的构造方法,用于更精细地控制线程的创建和执行。
高级程序员修炼之道-Android培训系列课程之ContentProvider5
Content Providers AndroidContent providers manage access to a structured set of data. They encapsulate the data, and provide mechanisms for defining data security. Content providers are the standard interface that connects data in one process with code running in another process.Content providers Content providers Content providersContent providersContent ProvidersWhen you want to access data in a content provider, you usethe ContentResolver object in your application's Context to communicate with the provider as a client. The ContentResolver object communicates with the provider object, an instance of a class that implements ContentProvider. The provider object receives data requests from clients, performs the requested action, and returns the results.Content ProvidersContext ContentResolver client provider ContentResolver ContentProvider provider Provider (client)Android Content Provider ContentProvider SQLite Content ProviderContent Providers Decide if you need a content provider. You need to build a content provider if you want to provide one or more of the following features:You want to offer complex data or files to other applications.You want to allow users to copy complex data from your app into otherapps.You want to provide custom search suggestions using the searchframework.Content Providers1.2.3.Content Provider URI URI URI authority authority authority If your Android package name is com.example.<appname>, you should give your provider the authority com.example.<appname>.provider. authorityURI content://<authority>/<path>/<id> path id idContent Provider URI[java]view plaincopyprint?1.publicclassExampleProviderextendsContentProvider{...2.// Creates a UriMatcher object.3.privatestaticfinalUriMatcher sUriMatcher;...4./*5.* The calls to addURI() go here, for all of the content URI patterns that the provider6.* should recognize. For this snippet, only the calls for table 3 are shown.7.*/...8./*9.* Sets the integer value for multiple rows in table 3 to 1. Notice that no wildcard is used10.* in the path11.*/12.sUriMatcher.addURI("com.example.app.provider","table3",1);13.14./*15.* Sets the code for a single row to 2. In this case, the "#" wildcard is16.* used. "content://com.example.app.provider/table3/3" matches, but17.* "content://com.example.app.provider/table3 doesn't.18.*19.* *: Matches a string of any valid characters of any length.20.* #: Matches a string of numeric characters of any length.21.22.*/23.sUriMatcher.addURI("com.example.app.provider","table3/#",2);...24.// Implements ContentProvider.query()25.publicCursor query(26.Uri uri,27.String[] projection,28.String selection,29.String[] selectionArgs,30.String sortOrder){...31./*32.* Choose the table to query and a sort order based on the code returned for the incoming33.* URI. Here, too, only the statements for table 3 are shown.34.*/35.switch(sUriMatcher.match(uri)){36.37.38.// If the incoming URI was for all of table339.case1:40.41.if(TextUtils.isEmpty(sortOrder)) sortOrder ="_ID ASC";42.break;43.44.// If the incoming URI was for a single row45.case2:46.47./*48.* Because this URI was for a single row, the _ID value part is49.* present. Get the last path segment from the URI; this is the _ID value.50.* Then, append the value to the WHERE clause for the query51.*/52.selection = selection +"_ID = " uri.getLastPathSegment();53.break;54.55.default:56....57.// If the URI is not recognized, you should do some error handling here.58.}59.// call the code to actually do the query }ContentProviderquery()Retrieve data from your provider. Use the arguments to select the table to query, the rows and columns to return, and the sort order of the result. Return the data as a Cursor object.insert()Insert a new row into your provider. Use the arguments to select the destination table and to get the column values to use. Return a content URI for the newly-inserted row.update()Update existing rows in your provider. Use the arguments to select the table and rows to update and to get the updated column values. Return the number of rows updated.delete()Delete rows from your provider. Use the arguments to select the table and the rows to delete. Return the number of rows deleted.getType()Return the MIME type corresponding to a content URI. This method is described in more detail in the section Implementing Content Provider MIME Types.onCreate()Initialize your provider. The Android system calls this method immediately after it creates your provider. Notice that your provider is not created until a ContentResolver object tries to access it.SQLite Content Provider SQLiteOpenHelper MainDatabaseHelper main[java]view plaincopyprint?1.// A string that defines the SQL statement for creating a tableprivatestaticfinalStringSQL_CREATE_MAIN ="CREATE TABLE "+2."main "+ // Table's name3."("+ // The columns in the table4." _ID INTEGER PRIMARY KEY, "+5." WORD TEXT"6." FREQUENCY INTEGER "+7." LOCALE TEXT )";.../**8.* Helper class that actually creates and manages the provider's underlying data repository.9.*/protectedstaticfinalclassMainDatabaseHelperextendsSQLiteOpenHelper{10.11./*12.* Instantiates an open helper for the provider's SQLite data repository13.* Do not do database creation and upgrade here.14.*/15.MainDatabaseHelper(Context context){16.super(context, DBNAME,null,1);17.}18.19./*20.* Creates the data repository. This is called when the provider attempts to open the21.* repository and SQLite reports that it doesn't exist.22.*/23.publicvoid onCreate(SQLiteDatabase db){24.25.// Creates the main table26.db.execSQL(SQL_CREATE_MAIN);27.} }ContentProvider SQLite client[java]view plaincopyprint?1.publicclassExampleProviderextendsContentProvider2.3./*4.* Defines a handle to the database helper object. The MainDatabaseHelper class is defined5.* in a following snippet.6.*/7.privateMainDatabaseHelper mOpenHelper;8.9.// Defines the database name10.privatestaticfinalString DBNAME ="mydb";11.12.// Holds the database object13.privateSQLiteDatabase db;14.15.publicboolean onCreate(){16.17./*18.* Creates a new helper object. This method always returns quickly.19.* Notice that the database itself isn't created or opened20.* until SQLiteOpenHelper.getWritableDatabase is called21.*/22.mOpenHelper =newSQLiteOpenHelper(23.getContext(), // the application context24.DBNAME, // the name of the database)25.null, // uses the default SQLite cursor26.1 // the version number27.);28.29.returntrue;30.}31.32....33.34.// Implements the provider's insert method35.publicCursor insert(Uri uri,ContentValues values){36.// Insert code here to determine which table to open, handle error-checking, and so forth37./*38.* Gets a writeable database. This will trigger its creation if it doesn't already exist.39.*40.*/41.db = mOpenHelper.getWritableDatabase();42.} }Content Providers1.Content Providers Android client data source2.Content Providers3. Content Providers ContentProvider ContentProvider URIContentProvider AndroidAndroid ——Content ProvidersContacts Provider AndroidContacts ProviderAndroid URIContactsContract.Contacts tableRows representing different people, based on aggregations of raw contact rows.ContactsContract.RawContacts tableRows containing a summary of a person's data, specific to a user account and type.ContactsContract.Data tableRows containing the details for raw contact, such as email addresses or phone numbers.Contacts RawContacts DataRow ContactsA raw contact represents a person's data coming from a single account type and account name. Because the Contacts Provider allows more than one online service as the source of data for a person, the Contacts Provider allowsmultiple raw contacts for the same person. Multiple raw contacts also allow a user to combine a person's data from more than one account from the same account type.Row contactContacts Provider Row Contacts Row Contacts Column name Use NotesACCOUNT_NAME The account name for the account type that's the source ofthis raw contact. For example, the account name of a Google account is one of the device owner's Gmail addresses. See the next entry for ACCOUNT_TYPE for more information.The format of this name is specific to its account type. It is not necessarily an emailaddress.ACCOUNT_TYPE The account type that's the source of this raw contact. For example, the account type of a Google account iscom.google . Always qualify your account type with a domain identifier for a domain you own or control. This will ensure thatyour account type is unique.An account type that offers contacts datausually has an associated sync adapter that synchronizes with the ContactsProvider. DELETED The "deleted" flag for a raw contact. This flag allows the Contacts Provider tomaintain the row internally until syncadapters are able to delete the row fromtheir servers and then finally delete the rowfrom the repository.ACCOUNT_NAME sanpleuser@ ACCOUNT_TYPE Google com.googleMost of the data for a raw contact isn't stored in the ContactsContract.RawContacts table. Instead, it's stored in one or more rows in the ContactsContract.Data table. Each data row has acolumn Data.RAW_CONTACT_ID that contains the RawContacts._ID value of its parent ContactsContract.RawContacts row.raw contacts RowContacts Data Data.RAW_CONTACT_ID RawContacts RawContacts._ID, RawContacts Row Contacts To understand how raw contacts work, consider the user "Emily Dickinson"who has the following three user accounts defined on her device:emily.dickinson@emilyd@Twitter account "belle_of_amherst"This user has enabled Sync Contacts for all three of these accounts in the Accounts settings.Suppose Emily Dickinson opens a browser window, logs into Gmail asemily.dickinson@, opens Contacts, and adds "Thomas Higginson".Later on, she logs into Gmail as emilyd@ and sends an email to "Thomas Higginson", which automatically adds him as a contact. She also follows "colonel_tom" (Thomas Higginson's Twitter ID) on Twitter.The Contacts Provider creates three raw contacts as a result of this work:1. A raw contact for "Thomas Higginson" associated withemily.dickinson@. The user account type is Google.2. A second raw contact for "Thomas Higginson" associated withemilyd@. The user account type is also Google. There is asecond raw contact even though the name is identical to a previous name, because the person was added for a different user account.3. A third raw contact for "Thomas Higginson" associated with"belle_of_amherst". The user account type is Twitter.gmail twitter gmail gmail gmail twitter RawContacts gmailGoogle gmail Google Twitter TwitterData Data Notice that different types of data are stored in this single table. Display name, phone number, email, postal address, photo, and website detail rows are all found in the ContactsContract.Data table. To help manage this, the ContactsContract.Data table has some columns with descriptive names, and others with generic names. The contents of a descriptive-name column have the same meaning regardless of the type of data in the row, while the contents of a generic-name column have different meanings depending on the type of data.ContactsContract.Data DataSome examples of descriptive column names are:RAW_CONTACT_IDRawContact _IDMIMETYPEThe type of data stored in this row, expressed as a custom MIME type. The Contacts Provider uses the MIME types defined in the subclasses ofmonDataKinds. These MIME types are open source, and can be used by any application or sync adapter that works with the Contacts Provider.MIMETYPE CommonDataKinds Generic column namesThere are 15 generic columns named DATA1 through DATA15 that are generally available and an additional four generic columns SYNC1 through SYNC4 that should only be used by sync adapters. The generic column name constants always work, regardless of the type of data the row contains.The DATA1 column is indexed. The Contacts Provider always uses thiscolumn for the data that the provider expects will be the most frequent target of a query. For example, in an email row, this column contains the actual email address.By convention, the column DATA15 is reserved for storing Binary Large Object (BLOB) data such as photo thumbnails.DATA1 DATA15 15 DATA1 Contacts Provider DATA15 BLOB(Binary Large Object)monDataKindsFor example, the monDataKinds.Email class defines type-specific column name constants for a ContactsContract.Data row that has the MIME type Email.CONTENT_ITEM_TYPE . The class contains the constant ADDRESS for the email address column. The actual value of ADDRESS is "data1", which is the same as the column's generic name.CommonDataKinds.Email ContactsContract.Data RAW_CONTACT_ID RawContact. DATA1 AddressCommonDataKinds Mapping classType of dataNotes monDataKinds.StructuredNam The name A raw contactedata for the raw contact associate d with this data row.has only one of these rows. monDataKinds.PhotoThe main photo for the raw contact associate d with this data row.A raw contact has only one of these rows. monDataKinds.EmailAn email address for the raw contact associate d withA raw contact can have multiple email addresses.this data row.monDataKinds.StructuredPost al A postaladdressfor therawcontactassociated withthis datarow.A raw contactcan havemultiplepostaladdresses.monDataKinds.GroupMembers hip Anidentifierthat linksthe rawcontactto one ofthegroups intheContactsProvider.Groups are anoptionalfeature of anaccount typeand accountname. They'redescribed inmore detail inthesection Contact groups.Android Content Providers ——Contacts Provider Contacts Contacts RawContacts Android ID Data Data RawContacts ID Data Android Android Contacts Contacts IDContacts RawContacts Gmail Twitter Data AndroidIntentTask Action DataMIME type NotesPick a conta ct from a listACTION_PI CK One of:Contacts.CONTENT_URI , which displays a list of contacts.Phone.CONTENT_URI , which displays a list of phone numbers for a raw contact.StructuredPostal.CONTENT_U RI , which displays a list of postal addresses for a raw contact.Email.CONTENT_URI , whichNot usedDisplays a list of raw contacts or a list of data from a raw contact, depending on the content URI type you supply. Call startActivityForResult(), which returns the content URI of the selected row. The form of the URI is the table's content URI with the row'sLOOKUP_ID appended to it. The device's contacts appdisplays a list of email addresses for a raw contact.delegates read and write permissions to this content URI for the life of your activity. See the Content Provider Basics guide for more details.Insert a new raw conta ctInsert.ACTI ONN/A RawContacts.CONTENT_TY PE , MIME type for a set of raw contacts.Displays the device's contacts application's Add Contact screen. The extras values you add to the intent are displayed. If sent with startActivityForResult(), the content URI of the newly-added raw contact is passed back to youractivity's onActivityResult()cal lback method in theIntent argument, in the "data" field. To get the value, call getData().Edit a conta ctACTION_ED ITCONTENT_LOOKUP_URI for the contact. The editor activity will allow the user to edit any of the data associated with this contact.Contacts.CONTENT_ITEM_T YPE , a single contact. Displays the Edit Contactscreen in the contacts application. The extras values you add to the intent are displayed. When the user clicks Done to save the edits, your activity returns to the foreground.Intent // Gets values from the UIString name = mContactNameEditText.getText().toString(); String phone = mContactPhoneEditText.getText().toString(); String email = mContactEmailEditText.getText().toString(); String company = mCompanyName.getText().toString(); String jobtitle = mJobTitle.getText().toString();// Creates a new intent for sending to the device's contacts application Intent insertIntent =newIntent(ContactsContract.Intents.Insert.ACTION); // Sets the MIME type to the one expected by the insertion activity insertIntent.setType(ContactsContract.RawContacts.CONTENT_TYPE); // Sets the new contact name-Android ContentProvider 21/21 insertIntent.putExtra(, name);// Sets the new company and job titleinsertIntent.putExtra(PANY, company);insertIntent.putExtra(ContactsContract.Intents.Insert.JOB_TITLE, jobtitle);<uses-permission android:name="android.permission.READ_CONTACTS"><uses-permission android:name="android.permission.WRITE_CONTACTS">。
高级程序员修炼之道-Android培训系列课程之Service1
Service
if (mediaPlayer != null) { mediaPlayer.stop(); mediaPlayer.release(); } } @Override public void onStart(Intent intent, int startId) { Log.v(TAG, "onStart"); if (intent != null) { Bundle bundle = intent.getExtras(); if (bundle != null) { int op = bundle.getInt("op"); switch (op) { case 1: play(); break; case 2: stop(); break; case 3: pause(); break; } } } } public void play() { if (!mediaPlayer.isPlaying()) { mediaPlayer.start(); } } public void pause() { if (mediaPlayer != null && mediaPlayer.isPlaying()) { mediaPlayer.pause(); } } public void stop() { if (mediaPlayer != null) { mediaPlayer.stop(); try { // stop start mediaPlayer.prepare(); } catch (IOException ex) {
) --> onUnbind
Service onStart onCreate onBind onUnbind onDestory service SD
高级程序员修炼之道-Android培训系列课程之ContentProvider2
Content Provider1 ContentProvider ContentProvide2 ContentProvider3 Android ContentProviderContentProviderquery(),insert(),update(),delete(),getType(),onCreate()URI1 ContentProvider URI URI ContentProvider2 Android ContentProvider android.provider A B C D 4A Content Provider "content://"B URI Content Provider URI authorities ContentProvider . ;"content://hx.android.text.myprovider"C ok "content://hx.android.text.myprovider/tablename"D URI ID id ID "content://hx.android.text.myprovider/tablename/#" # idContentProviderContentProvider ContentProvider1 CONTENT_URI ContentProviderpublic static final Uri CONTENT_URI =Uri.parse("content://com.example.codelab.transportationprovider");contentCom.exmaple.codelab.transportationproviderUri.parse UriProvider CONTENT_URIcontent://com.example.codelab.transportationprovider/traincontent://com.example.codelab.transportationprovider/air/domesticcontent://com.example.codelab.transportationprovider/air/international_id2 ContentProviderpublic class FirstContentProvider extends ContentProviderContentProvider UriMatcher UriMatcher match(Uri uri) Uri Uri Uripublic static final UriMatcher uriMatcher;static{uriMatcher=n ew U riMatcher(UriMatcher.NO_MATCH);uriMatcher.addURI(Book.AUTHORITY,"item",B ook.ITEM);uriMatcher.addURI(Book.AUTHORITY,"item/#",B ook.ITEM_ID);}UriMatcher ContentProvider Uri match() -1 UriMatcher.NO_MATCH addURI() URI ContentProvider AUTHORITY # * match() URIsMatcher.addURI(“com.test.provider.personprovider”, “person”, 1); match()content://com.test.provider.personprovider/person 13 query,insert,update,delete,getType onCreate4 AndroidManifest.xml<!-- android:name ContentProviderandroid:authorities FirstProvidermetaData AUTHORITY--><provider android:name="com.bj.FirstContentProvider"android:authorities="com.bj.firstcontentprovider"/>Activity19Activity.javapublic class Activity19Activity extends Activity {private Button queryButton = null;private Button insertButton = null;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(yout.main);queryButton = (Button) this.findViewById(R.id.query);queryButton.setOnClickListener(newQueryListener());insertButton = (Button) this.findViewById(R.id.insert);insertButton.setOnClickListener(newInsertListener());System.out.println(getContentResolver().getType(erTableMetaData.CONTENT_U RI));}class InsertListener implementsOnClickListener {@Overridepublic void onClick(View v) {// TODOAuto-generated method stubContentValues values = new ContentValues();values.put(ER_NAME,"michal");Uri uri = getContentResolver().insert(erTableMetaData.CONTENT_URI,values);System.out.println("uri--->" + uri.toString());}}class QueryListener implementsOnClickListener {public void onClick(View v) {Cursor c = getContentResolver().query(erTableMetaData.CONTENT_URI, null,null, null, null);while (c.moveToNext()) {System.out.println(c.getString(c.getColumnIndex("username")));}}}}FirstContentProvider.javapublic class FirstContentProvider extendsContentProvider {// ContentProvider Uri UriMatcher // uripublic static final UriMatcher uriMatcher;//public static final int INCOMING_USER_COLLECTION = 1;public static final int INCOMING_USER_SINGLE = 2;private DatabaseHelper dh;static {// users /uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);uriMatcher.addURI(FirstProvidermetaData.AUTHORITY, "users",INCOMING_USER_COLLECTION);uriMatcher.addURI(FirstProvidermetaData.AUTHORITY, "users/#",INCOMING_USER_SINGLE);}// sql//public static HashMap<String,String> userProjectionMap;static{userProjectionMap = newHashMap<String,String>();userProjectionMap.put(UserTableMetaData._ID, UserTableMetaData._ID ); userProjectionMap.put(ER_NAME, ER_NAME); }@Overridepublic int delete(Uri uri, String selection, String[] selectionArgs) {// TODOAuto-generated method stubSystem.out.println("delete");return 0;}// URI URI// URI@Overridepublic String getType(Uri uri) {// TODOAuto-generated method stubSystem.out.println("getType");switch (uriMatcher.match(uri)) {case INCOMING_USER_COLLECTION:// UserTableMetaData FirstProvidermetaDatareturn UserTableMetaData.CONTENT_TYPE;case INCOMING_USER_SINGLE:return UserTableMetaData.CONTENT_TYPE_ITEM;default:throw new IllegalArgumentException("Unknown uri" + uri);}}@Overridepublic Uri insert(Uri uri, ContentValues values) {// TODOAuto-generated method stubSystem.out.println("insert");SQLiteDatabase db = dh.getWritableDatabase();// -1long rowId = db.insert(UserTableMetaData.TABLE_NAME,null, values);if(rowId>0){// rowId//contentUris UriUri insertedUserUri = ContentUris.withAppendedId(UserTableMetaData.CONTENT_URI, rowId); //getContext().getContentResolver().notifyChange(insertedUserUri, null);return insertedUserUri;}throw new SQLException("Failed to insert row into "+uri);}// ContentProvider// DatabaseHelper@Overridepublic boolean onCreate() {// TODOAuto-generated method stub//getContext contextdh = new DatabaseHelper(getContext(),FirstProvidermetaData.DATABASE_NAME);System.out.println("on create");SQLiteDatabase db = dh.getReadableDatabase();return true;}//projection//selection:where ?//selectionArgs://sortOrder:@Overridepublic Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder) {// TODOAuto-generated method stubSystem.out.println("query");//SQLiteQueryBuilder qb = new SQLiteQueryBuilder();switch(uriMatcher.match(uri)){case INCOMING_USER_COLLECTION://qb.setTables(UserTableMetaData.TABLE_NAME);qb.setProjectionMap(userProjectionMap);break;case INCOMING_USER_SINGLE:qb.setTables(UserTableMetaData.TABLE_NAME);qb.setProjectionMap(userProjectionMap);// where getPathSegments uri path content:XXX/user/1 get(1) 1 qb.appendWhere(UserTableMetaData._ID+"="+uri.getPathSegments().get(1));break;}String orderBy;if(TextUtils.isEmpty(sortOrder)){orderBy = UserTableMetaData.DEFAULT_SORT_ORDER;}else{orderBy = sortOrder;}SQLiteDatabase db = dh.getWritableDatabase();// query qbCursor c = qb.query(db, projection, selection, selectionArgs, null, null, orderBy);//c.setNotificationUri(getContext().getContentResolver(), uri);System.out.println("query");return c;}@Overridepublic int update(Uri uri, ContentValues values, String selection,String[] selectionArgs) {// TODOAuto-generated method stubreturn 0;}}FirstProvidermetaData.javapublic class FirstProvidermetaData {public static final String AUTHORITY="com.bj.firstcontentprovider"; // contentprovider //public static final String DATABASE_NAME = "FirstProvider.db";//public static final int DATABASE_VERSION = 1;//public static final String USERS_TABLE_NAME = "users";public static final class UserTableMetaData implements BaseColumns{//public static final String TABLE_NAME="users";// ContentProvider URIpublic static final Uri CONTENT_URI=Uri.parse("content://"+AUTHORITY+"/users");public static final String CONTENT_TYPE="vnd.android.cursor.dir/er";public static final String CONTENT_TYPE_ITEM="vnd.android.cursor.item/er";// users namepublic static final String USER_NAME="name";//public static final String DEFAULT_SORT_ORDER="_id desc";}}。
高级程序员修炼之道-Android培训系列课程之Service5
android MessengerMessenger:Handler others (mMessenger.send(Message msg) ) Message ( Message ) Handler Messenger MessengerHandler+Message HandlerAndroid bindler Handler bindlerAPI MessengermMessenger = new Messenger(mHandler)bindlerServiceonBind bindlerreturn mMessenger.getBinder();4. bindlerpublic void onServiceConnected(ComponentName name, IBinder service) {rMessenger = new Messenger(service);......}new Messengerpublic Messenger(IBinder target) { mTarget = IMessenger.Stub.asInterface(target); }mTarget AidlrMessenger.send(msg);Handler handlerMessage(Message msg) Handler Messenger mHandler .send(msg) msm.replyTo = mMessenger / cMessenger = msg.replyTo; cMessenger.send(message);Handler handlerMessage messageApiDemoService code:[java]view plaincopyprint?1.public class MessengerService extends Service {2./** For showing and hiding our notification. */3.NotificationManager mNM;4./** Keeps track of all current registered clients. */5.ArrayList<Messenger> mClients = new ArrayList<Messenger>();6./** Holds last value set by a client. */7.int mValue = 0;8.9./**10.* Command to the service to register a client, receiving callbacks11.* from the service. The Message's replyTo field must be a Messenger of12.* the client where callbacks should be sent.13.*/14.static final int MSG_REGISTER_CLIENT = 1;15.16./**17.* Command to the service to unregister a client, ot stop receiving callbacks18.* from the service. The Message's replyTo field must be a Messenger of19.* the client as previously given with MSG_REGISTER_CLIENT.20.*/21.static final int MSG_UNREGISTER_CLIENT = 2;22.23./**24.* Command to service to set a new value. This can be sent to the25.* service to supply a new value, and will be sent by the service to26.* any registered clients with the new value.27.*/28.static final int MSG_SET_VALUE = 3;29.30./**31.* Handler of incoming messages from clients.32.*/33.class IncomingHandler extends Handler {34.@Override35.public void handleMessage(Message msg) {36.switch (msg.what) {37.case MSG_REGISTER_CLIENT:38.mClients.add(msg.replyTo);39.break;40.case MSG_UNREGISTER_CLIENT:41.mClients.remove(msg.replyTo);42.break;43.case MSG_SET_VALUE:44.mValue = msg.arg1;45.for (int i = mClients.size() - 1; i >= 0; i --) {46.try {47.mClients.get(i).send(Message.obtain(null,48.MSG_SET_VALUE, mValue, 0));49.} catch (RemoteException e) {50.// The client is dead. Remove it from the list;51.// we are going through the list from back to front52.// so this is safe to do inside the loop.53.mClients.remove(i);54.}55.}56.break;57.default:58.super.handleMessage(msg);59.}60.}61.}62.63./**64.* Target we publish for clients to send messages to IncomingHandler.65.*/66.final Messenger mMessenger = new Messenger(new IncomingHandler());67.68.@Override69.public void onCreate() {70.mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);71.72.// Display a notification about us starting.73.showNotification();74.}75.76.@Override77.public void onDestroy() {78.// Cancel the persistent notification.79.mNM.cancel(R.string.remote_service_started);80.81.// Tell the user we stopped.82.Toast.makeText(this, R.string.remote_service_stopped, Toast.LENGTH_SHORT).show();83.}84.85./**86.* When binding to the service, we return an interface to our messenger87.* for sending messages to the service.88.*/89.@Override90.public IBinder onBind(Intent intent) {91.return mMessenger.getBinder();92.}93.94./**95.* Show a notification while this service is running.96.*/97.private void showNotification() {98.// In this sample, we'll use the same text for the ticker and the expanded notification99.CharSequence text = getText(R.string.remote_service_started);100.101.// Set the icon, scrolling text and timestamp102.Notification notification = new Notification(R.drawable.stat_sample, text,103.System.currentTimeMillis());104.105.// The PendingIntent to launch our activity if the user selects this notification 106.PendingIntent contentIntent = PendingIntent.getActivity(this, 0,107.new Intent(this, Controller.class), 0);108.109.// Set the info for the views that show in the notification panel.110.notification.setLatestEventInfo(this, getText(R.string.remote_service_label),111.text, contentIntent);112.113.// Send the notification.114.// We use a string id because it is a unique number. We use it later to cancel.115.mNM.notify(R.string.remote_service_started, notification);116.}117.}Client code:[java]view plaincopyprint?1.public class MessengerServiceActivities {2./**3.* Example of binding and unbinding to the remote service.4.* This demonstrates the implementation of a service which the client will5.* bind to, interacting with it through an aidl interface.</p>6.*7.* <p>Note that this is implemented as an inner class only keep the sample8.* all together; typically this code would appear in some separate class.9.*/10.public static class Binding extends Activity {11.12./** Messenger for communicating with service. */13.Messenger mService = null;14./** Flag indicating whether we have called bind on the service. */15.boolean mIsBound;16./** Some text view we are using to show state information. */17.TextView mCallbackText;18.19./**20.* Handler of incoming messages from service.21.*/22.class IncomingHandler extends Handler {23.@Override24.public void handleMessage(Message msg) {25.switch (msg.what) {26.case MessengerService.MSG_SET_VALUE:27.mCallbackText.setText("Received from service: " + msg.arg1);28.break;29.default:30.super.handleMessage(msg);31.}32.}33.}34.35./**36.* Target we publish for clients to send messages to IncomingHandler.37.*/38.final Messenger mMessenger = new Messenger(new IncomingHandler());39.40./**41.* Class for interacting with the main interface of the service.42.*/43.private ServiceConnection mConnection = new ServiceConnection() {44.public void onServiceConnected(ComponentName className,45.IBinder service) {46.// This is called when the connection with the service has been47.// established, giving us the service object we can use to48.// interact with the service. We are communicating with our49.// service through an IDL interface, so get a client-side50.// representation of that from the raw service object.51.mService = new Messenger(service);52.mCallbackText.setText("Attached.");53.54.// We want to monitor the service for as long as we are55.// connected to it.56.try {57.Message msg = Message.obtain(null,58.MessengerService.MSG_REGISTER_CLIENT);59.msg.replyTo = mMessenger;60.mService.send(msg);61.62.// Give it some value as an example.63.64.msg = Message.obtain(null,65.MessengerService.MSG_SET_VALUE, this.hashCode(), 0);66.67.mService.send(msg);68.} catch (RemoteException e) {69.// In this case the service has crashed before we could even70.// do anything with it; we can count on soon being71.// disconnected (and then reconnected if it can be restarted)72.// so there is no need to do anything here.73.}74.75.// As part of the sample, tell the user what happened.76.Toast.makeText(Binding.this, R.string.remote_service_connected,77.Toast.LENGTH_SHORT).show();78.}79.80.public void onServiceDisconnected(ComponentName className) {81.// This is called when the connection with the service has been82.// unexpectedly disconnected -- that is, its process crashed.83.mService = null;84.mCallbackText.setText("Disconnected.");85.86.// As part of the sample, tell the user what happened.87.Toast.makeText(Binding.this, R.string.remote_service_disconnected,88.Toast.LENGTH_SHORT).show();89.}90.};91.92.void doBindService() {93.// Establish a connection with the service. We use an explicit94.// class name because there is no reason to be able to let other95.// applications replace our component.96.bindService(new Intent(Binding.this,97.MessengerService.class), mConnection, Context.BIND_AUTO_CREATE);98.mIsBound = true;99.mCallbackText.setText("Binding.");100.}101.102.void doUnbindService() {103.if (mIsBound) {104.// If we have received the service, and hence registered with105.// it, then now is the time to unregister.106.if (mService != null) {107.try {108.Message msg = Message.obtain(null,109.MessengerService.MSG_UNREGISTER_CLIENT);110.msg.replyTo = mMessenger;111.mService.send(msg);112.} catch (RemoteException e) {113.// There is nothing special we need to do if the service114.// has crashed.115.}116.}117.118.// Detach our existing connection.119.unbindService(mConnection);120.mIsBound = false;121.mCallbackText.setText("Unbinding.");122.}123.}124.125.126./**127.* Standard initialization of this activity. Set up the UI, then wait 128.* for the user to poke it before doing anything.129.*/130.@Override131.protected void onCreate(Bundle savedInstanceState) {132.super.onCreate(savedInstanceState);133.134.setContentView(yout.messenger_service_binding);135.136.// Watch for button clicks.137.Button button = (Button)findViewById(R.id.bind);138.button.setOnClickListener(mBindListener);139.button = (Button)findViewById(R.id.unbind);140.button.setOnClickListener(mUnbindListener);141.142.mCallbackText = (TextView)findViewById(R.id.callback);143.mCallbackText.setText("Not attached.");144.}145.146.private OnClickListener mBindListener = new OnClickListener() { 147.public void onClick(View v) {148.doBindService();149.}150.};151.152.private OnClickListener mUnbindListener = new OnClickListener() { 153.public void onClick(View v) {154.doUnbindService();155.}156.};157.}158.}register:[html]view plain copyprint?1.<service android:name=".app.MessengerService"-Android Service 2.android:process=":remote"/>11/11。
thread的用法总结大全
thread的用法总结大全Thread是一个多线程编程的概念,在许多编程语言中都有Thread类或相关的API提供多线程编程的功能。
它允许程序同时执行多个任务,使得程序能够更加高效地利用计算机的资源,同时提高程序的响应速度和并发性。
以下是Thread的用法总结大全:1. 创建线程:- 继承Thread类,重写run()方法,并调用start()方法启动线程。
- 实现Runnable接口,重写run()方法,并通过Thread类的构造函数传入实现了Runnable接口的类。
2. 控制线程:- 使用start()方法启动线程。
- 使用join()方法等待线程执行完毕。
- 使用sleep()方法暂停线程的执行一段时间。
- 使用yield()方法让出当前线程的执行权。
3. 线程同步:- 使用synchronized关键字实现线程的互斥访问。
- 使用wait()、notify()和notifyAll()方法实现线程的等待和唤醒。
- 使用Lock和Condition接口实现线程的同步。
4. 线程间通信:- 使用共享对象作为通信的媒介,如通过共享变量进行数据的传递。
- 使用等待-通知机制实现线程间的通信,即wait()和notify()方法的配合使用。
5. 线程安全:- 使用线程安全的数据结构,如ConcurrentHashMap和CopyOnWriteArrayList。
- 使用线程安全的类,如AtomicInteger和CountDownLatch。
- 使用synchronized关键字或Lock接口实现线程安全。
6. 线程池:- 使用线程池管理线程的创建和销毁,提高线程的利用率和执行效率。
- 使用Executors类创建线程池,如newFixedThreadPool()、newCachedThreadPool()等。
- 使用ThreadPoolExecutor类自定义线程池的参数,如核心线程数、最大线程数和任务队列等。
thread常用方法
thread类是多线程编程中的一个重要概念。
一个thread对象就表示一个线程的活动。
要做多线程编程,创建thread对象是首要步骤。
thread类中常用的方法有:
1. start(): 启动一个线程,并执行run()方法。
这是最重要的一个方法,用于开始一个线程活动。
2. run(): 定义线程要完成的任务。
通常需要override此方法来指定线程任务内容。
3. join(): 等待线程终止。
可以对一个线程对象调用另一个线程的join()方法,此线程就会等待join线程结束后才继续执行。
4. interrupt(): 中断线程。
调用该方法会设置线程的中断标志。
可以用来中断正在执行的线程。
5. sleep(): 让当前线程暂停指定毫秒时间。
这可以用于需要等待或周期执行某任务的情况。
6. getName()/setName():获得/设置线程名称。
使用thread创建多线程代码范例如下:
1) 继承Thread类,重写run()方法;
2) 创建Thread实例,调用start()方法开始执行。
这样就可以启动一个新的线程,任务定义在run()中。
想要多个线程就重复创建更多Thread实例。
通过join等方法可以实现线程间协作。
综上所述,thread类封装了线程活动的基本过程,关键是理解start(),run(),join()等方法的用法,这样可以灵活控制多线程的执行顺序与协作方式。
在编写高效并发程序时,合理利用线程是最重要的技能。
Android应用开发中的多线程编程技术详解
Android应用开发中的多线程编程技术详解随着移动设备不断普及,Android应用的用户数量愈加庞大,因此,开发高质量、高效率的Android应用已经成为了一种竞争优势。
而在Android应用开发中,多线程编程技术就是必不可少的一个重要领域。
本文将详细探讨Android应用开发中的多线程编程技术,包括线程的概念、线程池和Handler机制、异步任务和Loader、消息队列和消息循环机制等内容。
通过深入了解这些多线程编程技术,开发者们可以更好地开发出高效率、高响应程序与丝滑顺畅的用户体验。
一、线程的概念线程可以理解为是一种轻量级进程(Lightweight Process),它是计算机中已被分配了系统资源的基本单位,可以执行一系列指令序列,并将结果返回给主线程。
在Android中,每个应用程序都是单独的进程,而每个进程又可以包含多个线程,这些线程使用操作系统调度算法来分享CPU资源,从而提高程序的执行效率和响应速度。
在Android中启动一个线程很简单,只需要使用Thread类即可。
一般情况下,我们需要自己定义一个类,这个类必须继承自Thread类,并重写其中的run()方法,run()方法中包含了子线程的代码逻辑。
下面是一个简单的线程启动示例:```javapublic class MyThread extends Thread {@Overridepublic void run() {// 线程代码逻辑super.run();}}//在主线程中启动MyThread线程MyThread thread = new MyThread();thread.start();```二、线程池和Handler机制虽然线程可以提高程序的响应速度和执行效率,但同时也存在一些问题。
比如,线程开启和销毁需要不少的时间和开销,频繁地调用可能会对系统稳定性产生影响。
因此,Android提供了线程池和Handler机制来解决这些问题。
程序员修炼之道
程序员修炼之道随着互联网和科技的快速发展,程序员成为了当代社会中不可或缺的一部分。
作为从事编程工作的人员,程序员不仅需要具备扎实的技术基础和编程能力,还需要通过修炼自身,提高自己的综合素质。
本文将探讨程序员修炼之道,帮助程序员们在职业生涯中迈出坚实的一步。
一、学无止境——持续学习的重要性在技术领域,只有学无止境才能跟上时代的步伐。
作为一名程序员,需要不断学习新的编程语言、框架和技术,以适应快速变化的行业需求。
通过参加培训班、自学教程、阅读专业书籍和博客,程序员能够不断提升自己的技术水平。
此外,还可以参与技术论坛、开源社区和技术交流会,与行业内的专家和同行交流,分享经验和学习心得。
二、善于解决问题——锻炼分析与解决问题的能力作为程序员,面对各种各样的技术难题是家常便饭。
善于解决问题是一名优秀程序员的基本素质之一。
在解决问题的过程中,程序员需要提炼问题的本质,找到问题的症结所在,并运用逻辑思维和技术知识找到解决方案。
通过不断面对和解决问题,程序员的分析和解决问题的能力将不断得到锻炼和提高。
三、良好的沟通能力——与人协作解决问题在现代企业中,团队合作是非常重要的。
良好的沟通能力对于程序员来说尤为重要。
程序员需要与产品经理、设计师和其他团队成员保持良好的合作关系,及时传递和掌握项目需求,解决问题,推进项目进展。
通过参与团队项目和多元化的沟通训练,程序员能够提高自己的沟通技巧,更好地与团队协作,共同完成项目目标。
四、代码质量与规范——追求优雅与高效优秀的程序员不仅需要编写可行的代码,还需要注重代码质量和规范。
编写高质量的代码可以提高代码的可读性和可维护性,减少潜在的问题和错误,提高程序的效率和稳定性。
程序员可以遵循编码规范,如命名规范、注释规范、代码缩进等,通过代码审查和单元测试持续改进代码质量。
五、持续追求创新——积极参与与贡献开源项目在当今开源的开发环境中,程序员通过参与开源项目可以扩展自己的技术视野、增加项目经验、学习最佳实践。
android高级编程 知识点
android高级编程知识点
Android高级编程涉及的知识点广泛,包括但不限于以下几个方面:
1. 性能优化:提高应用的运行效率,包括布局优化、内存管理、线程处理等。
2. 自定义视图和组件:创建自定义的视图和组件,包括自定义属性、样式、布局等。
3. 数据存储:使用不同的存储方式,如SharedPreferences、SQLite数据库、文件存储等。
4. 跨平台开发:使用跨平台技术,如React Native、Flutter等,实现一次编写多平台运行。
5. 高级UI设计:掌握Material Design、ConstraintLayout等高级UI设
计技术,实现美观的界面效果。
6. 网络编程:使用Retrofit、Volley等网络库进行网络请求和数据解析。
7. 安全性:了解常见的安全漏洞和攻击方式,如SQL注入、跨站脚本攻击等,并采取相应的防范措施。
8. 测试和调试:使用单元测试、集成测试和调试工具,确保应用的稳定性和可靠性。
9. 发布和管理:了解如何在Google Play商店发布和管理应用,以及如何
进行版本控制和持续集成。
10. 插件化开发:实现插件化应用,提高应用的模块化和可维护性。
以上知识点只是其中的一部分,掌握这些知识点可以帮助开发者更好地进行Android高级编程。
同时,不断学习和探索新技术也是非常重要的。
程序员修炼之道
程序员修炼之道随着时代的进步,科技蓬勃发展,程序员逐渐成为一个必不可少的职业角色。
但是,成为一个优秀的程序员仍然不是一件容易的事。
就像古希腊故事中的勇士一样,程序员也需要勇气、智慧和行动来赢得胜利。
那么,程序员的修炼之道又是什么呢?首先,程序员必须具备良好的态度和技能。
程序员往往需要掌握大量的技术知识,此外,他们需要掌握编程语言,以便编写可靠和精确的代码。
另外,程序员必须具备不断学习和更新技能的热情,因为科技技术一直在发展变化,程序员需要跟进这些新技术,以便能够打造出更加出色的代码。
此外,程序员还要有良好的抗压能力,在天时地利人和的情况下,可以一次性完成复杂的任务来将计划变成现实。
程序员也要具备合作精神。
程序员工作时往往可能会在合作中有所改善,因此,他们要学会拥抱和理解不同的意见,并能够更有效地利用自己的技能去完成这些任务。
他们需要掌握与团队的沟通技巧和团队协作技巧,包括理解不同的观点、负责分配任务和承担责任等等。
当然,所有的这些技能都是建立在程序员的持之以恒的努力之上的。
程序员必须勇于解决问题,不断尝试新的事物,并且具有恒心与耐心,才能够获得更好的成果。
此外,他们还需要具备创新意识,能够及时发现问题,并制定有效的解决方案,来提升自己的工作能力。
此外,令程序员成功不可忽略的一点就是对它的工作的热爱。
程序员必须对想要实现的一些事情有一份热情,才能够更好地将计划变成现实,发挥最大的效率。
综上所述,成为一个优秀程序员需要良好的态度、技能、抗压能力、合作精神和热爱,以及创新意识。
只有当程序员具备了这些要素,他们才能够从编程中获得真正的乐趣,享受成就感,并做出一些真正能够影响世界的事情。
程序员在修炼着这条道路,并且并将继续勇敢地走下去。
Android线程管理之Thread使用总结
Android线程管理之Thread使⽤总结前⾔最近在⼀直准备总结⼀下Android上的线程管理,今天先来总结⼀下Thread使⽤。
线程管理相关⽂章地址:实现Thread两种⽅式1.)继承Thread类/*** 继承Thread⽅式*/private class SyncThread extends Thread {SyncThread(String name) {super(name);}@Overridepublic void run() {//执⾏耗时操作}}⽰例:SyncThread syncThread1 = new SyncThread("线程⼀");SyncThread syncThread2 = new SyncThread("线程⼆");SyncThread syncThread3 = new SyncThread("线程三");syncThread1.start();syncThread2.start();syncThread3.start();2.)实现Runnable接⼝/*** 实现Runnable⽅式*/private class SyncRunnable implements Runnable {@Overridepublic void run() {//执⾏耗时操作}}⽰例:SyncRunnable syncRunnable = new SyncRunnable();Thread syncThread1 = new Thread(syncRunnable, "线程⼀");Thread syncThread2 = new Thread(syncRunnable, "线程⼆");Thread syncThread3 = new Thread(syncRunnable, "线程三");syncThread1.start();syncThread2.start();syncThread3.start();Thread主要函数run()//包含线程运⾏时所执⾏的代码start()//⽤于启动线程sleep()/sleep(long millis)//线程休眠,交出CPU,让CPU去执⾏其他的任务,然后线程进⼊阻塞状态,sleep⽅法不会释放锁yield()//使当前线程交出CPU,让CPU去执⾏其他的任务,但不会是线程进⼊阻塞状态,⽽是重置为就绪状态,yield⽅法不会释放锁join()/join(long millis)/join(long millis,int nanoseconds)//等待线程终⽌,直⽩的说就是发起该⼦线程的线程只有等待该⼦线程运⾏结束才能继续往下运⾏wait()//交出cpu,让CPU去执⾏其他的任务,让线程进⼊阻塞状态,同时也会释放锁interrupt()//中断线程,⾃stop函数过时之后,我们通过interrupt⽅法和isInterrupted()⽅法来停⽌正在运⾏的线程,注意只能中断已经处于阻塞的线程getId()//获取当前线程的IDgetName()/setName()//获取和设置线程的名字getPriority()/setPriority()//获取和这是线程的优先级⼀般property⽤1-10的整数表⽰,默认优先级是5,优先级最⾼是10,优先级⾼的线程被执⾏的机率⾼setDaemon()/isDaemo()//设置和判断是否是守护线程currentThread()//静态函数获取当前线程Thread线程主要状态(1) New ⼀旦被实例化之后就处于new状态(2) Runnable 调⽤了start函数之后就处于Runnable状态(3) Running 线程被cpu执⾏调⽤run函数之后就处于Running状态(4) Blocked 调⽤join()、sleep()、wait()使线程处于Blocked状态(5) Dead 线程的run()⽅法运⾏完毕或被中断或被异常退出,线程将会到达Dead状态如何停⽌⼀个线程通过上⾯的函数列表,我可以知道通过interrupt⽅法和isInterrupted()⽅法来停⽌正在运⾏的线程,⾸先必须先让线程处于阻塞状态/*** 销毁线程⽅法*/private void destroyThread() {try {if (null != thread && Thread.State.RUNNABLE == thread .getState()) {try {Thread.sleep(500);thread .interrupt();} catch (Exception e) {e.printStackTrace();}}} catch (Exception e) {e.printStackTrace();} finally {thread = null;}}Thread线程同步问题线程的同步是为了防⽌多个线程访问⼀个数据对象时,造成数据不⼀致的问题。
高级程序员修炼之道-Android培训系列课程之ContentProvider4
ContentProviderAndroid ContentResolver<!-- --><uses-permission android:name="android.permission.READ_CONTACTS" /><uses-permission android:name="android.permission.WRITE_CONTACTS" /><!-- uri -->content://com.android.contacts/contacts Uricontent://com.android.contacts/data/phones Uricontent://com.android.contacts/data/emails Email Uri<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="/apk/res/android"package="com.ljq.contact" android:versionCode="1"android:versionName="1.0"><application android:icon="@drawable/icon"android:label="@string/app_name"><uses-library android:name="android.test.runner"/><activity android:name=".ContactActivity"android:label="@string/app_name"><intent-filter><action android:name="android.intent.action.MAIN"/><categoryandroid:name="UNCHER"/></intent-filter></activity></application><uses-sdk android:minSdkVersion="7"/><instrumentationandroid:name="android.test.InstrumentationTestRunner"android:targetPackage="com.ljq.contact"android:label="Tests for My App"/><!-- --><uses-permission android:name="android.permission.READ_CONTACTS"/><uses-permission android:name="android.permission.WRITE_CONTACTS"/></manifest>package com.ljq.contact;import java.util.ArrayList;import android.content.ContentProviderOperation;import android.content.ContentProviderResult;import android.content.ContentResolver;import android.content.ContentUris;import android.content.ContentValues;import android.database.Cursor;import .Uri;import android.provider.ContactsContract;import android.provider.ContactsContract.Data;import android.provider.ContactsContract.RawContacts;import monDataKinds.Email;import monDataKinds.Phone;import monDataKinds.StructuredName;import android.test.AndroidTestCase;import android.util.Log;public class ContactTest extends AndroidTestCase{private static final String TAG = "ContactTest";/****/public void testGetContact(){ContentResolver contentResolver = this.getContext().getContentResolver();Uri uri = Uri.parse("content://com.android.contacts/contacts");Cursor cursor = contentResolver.query(uri, null, null, null, null);while(cursor.moveToNext()){//StringBuilder sb = new StringBuilder();String contactId =cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));String name =cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));sb.append("contactId=").append(contactId).append(",name=").append(name);//Cursor phones =contentResolver.query(monDataKinds.Phone.CONTENT_URI,null,monDataKinds.Phone.CONTACT_ID +" = "+ contactId,null, null);while(phones.moveToNext()){String phone = phones.getString(phones.getColumnIndex("data1"));sb.append(",phone=").append(phone);}// emailCursor emails =contentResolver.query(monDataKinds.Email.CONTENT_URI,null,C monDataKinds.Email.CONTACT_ID + " = " + contactId,null, null);while(emails.moveToNext()){String email = emails.getString(emails.getColumnIndex("data1"));sb.append(",email=").append(email);}Log.i(TAG, sb.toString());}}/*** RawContacts.CONTENT_URI rawContactId** data*/public void testInsert(){ContentValues values = new ContentValues();// RawContacts.CONTENT_URI rawContactIdUri rawContactUri =this.getContext().getContentResolver().insert(RawContacts.CONTENT_URI, values);long rawContactId = ContentUris.parseId(rawContactUri);// datavalues.clear();values.put(Data.RAW_CONTACT_ID, rawContactId);values.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);values.put(StructuredName.GIVEN_NAME, "zhangsan");this.getContext().getContentResolver().insert(android.provider.ContactsContract.Data.CONTENT_URI, values);// datavalues.clear();values.put(android.provider.ContactsContract.Contacts.Data.RAW_CONTACT_ID, rawContactId);values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);values.put(Phone.NUMBER, "5554");values.put(Phone.TYPE, Phone.TYPE_MOBILE);this.getContext().getContentResolver().insert(android.provider.ContactsContract.Data.CONTENT_URI, values);// data Emailvalues.clear();values.put(android.provider.ContactsContract.Contacts.Data.RAW_CONTACT_ID, rawContactId);values.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);values.put(Email.DATA, "ljq218@");values.put(Email.TYPE, Email.TYPE_WORK);this.getContext().getContentResolver().insert(android.provider.ContactsContract.Data.CONTENT_URI, values);}/****/public void testSave() throws Throwable{// reference\android\provider\ContactsContract.RawContacts.htmlArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();int rawContactInsertIndex = 0;ops.add(ContentProviderOperation.newInsert(RawContacts.CONTENT_URI).withValue(RawContacts.ACCOUNT_TYPE, null).withValue(RawContacts.ACCOUNT_NAME, null).build());// reference\android\provider\ContactsContract.Data.htmlops.add(ContentProviderOperation.newInsert(android.provider.ContactsContract.Data.CONTENT_U RI).withValueBackReference(Data.RAW_CONTACT_ID, rawContactInsertIndex).withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE).withValue(StructuredName.GIVEN_NAME, "lisi").build());ops.add(ContentProviderOperation.newInsert(android.provider.ContactsContract.Data.CONTENT_U RI).withValueBackReference(Data.RAW_CONTACT_ID, rawContactInsertIndex).withValue(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE).withValue(Phone.NUMBER, "5556").withValue(Phone.TYPE, Phone.TYPE_MOBILE).withValue(BEL, "").build());ops.add(ContentProviderOperation.newInsert(android.provider.ContactsContract.Data.CONTENT_U RI).withValueBackReference(Data.RAW_CONTACT_ID, rawContactInsertIndex).withValue(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE).withValue(Email.DATA, "lisi@").withValue(Email.TYPE, Email.TYPE_WORK).build());ContentProviderResult[] results = this.getContext().getContentResolver().applyBatch(ContactsContract.AUTHORITY,ops);for (ContentProviderResult result : results) {Log.i(TAG, result.uri.toString());}}}。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
android
android andriod Handler Looper Handler Android Looper android UI Handle Handle Handle Looper UI Looper
UI UI UI
Android Looper android UI Handler Handler Handler Looper UI Looper
UI UI UI
Handler Handler
?
0 1 2
class ChildThread extends Thread {
public void run() {
/*
* handler Looper.
*/
Looper.prepare();
/*
* handler
*
*/
mChildHandler = new Handler() {
public void handleMessage(Message msg) {
/*
* Do some expensive operations there.
*/
3
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9 } }; /* * */ Looper.loop(); } }
Handler handleMessage(…)
quit() ?
mChildHandler.getLooper().quit
();
?
1
2
3
4
5
6
7
8
9
1 0
1 1
1 2
1 3
1 4
1 5
1 6
1 7
1 8 /**
*
* @author allin.dev
*
*
*/
public class MainThread extends Activity {
private static final String TAG = "MainThread";
private Handler mMainHandler, mChildHandler;
private TextView info;
private Button msgBtn;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(yout.main);
info = (TextView) findViewById();
msgBtn = (Button) findViewById(R.id.msgBtn);
mMainHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
Log.i(TAG, "Got an incoming message from the child thread - " + (String) msg.obj);
//
info.setText((String) msg.obj);
}
};
new ChildThread().start();
1
9
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 4msgBtn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (mChildHandler != null) { // Message childMsg = mChildHandler.obtainMessage(); childMsg.obj = mMainHandler.getLooper().getThread().getName() + " says Hello"; mChildHandler.sendMessage(childMsg); Log.i(TAG, "Send a message to the child thread - " + (String)childMsg.obj); } } }); } public void onDestroy() { super.onDestroy(); Log.i(TAG, "Stop looping the child thread's message queue"); mChildHandler.getLooper().quit(); } class ChildThread extends Thread { private static final String CHILD_TAG = "ChildThread"; public void run() { this.setName("ChildThread"); // Handler Looper.prepare(); mChildHandler = new Handler() { @Override public void handleMessage(Message msg) { Log.i(CHILD_TAG, "Got an incoming message from the main thread - " + (String)msg.obj); try { // sleep(100); Message toMain = mMainHandler.obtainMessage(); toMain.obj = "This is " + this.getLooper().getThread().getName() + ". Did you send me \"" + (String)msg.obj + "\"?"; mMainHandler.sendMessage(toMain); Log.i(CHILD_TAG, "Send a message to the main thread - " + (String)toMain.obj); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
};
41
42
43
4
4
4
5
4
6
4
7
4
8
4
9
5
5
1
5
2
5
3
5
4
5
5
5
6
5
7
5
8
5
9
6
6
1
Log.i(CHILD_TAG, "Child handler is bound to - "+ mChildHandler.getLooper().getThread().getName()); // Looper.loop(); } } }
6 2
6 3
6 4
6 5
6 6
6 7
6 8
6 9
7 0
7 1
7 2
7 3
7 4
7 5
7 6
7 7
7 8
7 9
8 0
8 1
8 2
8
3
8 4
8 5
8 6
8 7
8 8
8 9
9 0
9 1
9 2
9 3
9 4
9 5
9 6
9 7
9 8
9 9
1 00
1 01
1 02
1 03
1 04
1 05
1 06
1 07
1
08。