1.5 用GCD执行与UI相关的任务
目的:为了并发你使用了GCD并且想知道与UI相关的APIs一起工作的最佳办法。
讨论:UI相关的任务必须在主线程中执行,所以主队列是在GCD中执行UI任务的唯一候选对象。我们可以使用dispatch_get_main_queue 函数得到处理分派队列的句柄。
这里有2中向主队列分派任务的方法,两者都是异步的,即使在任务没有执行的时候也让你的程序继续:
dispatch_async 函数
在分派队列上执行一个 Block Object.
dispatch_async_f函数
在分派队列上执行一个C函数。
dispatch_sync方法不能在主队列中调用,因为这会无限期的阻止线程并会导致你的应用死锁。所有通过GCD提交到主队列的任务必须是异步的。
dispatch_queue_t mainQueue = dispatch_get_main_queue();主队列用异步调用方法
dispatch_async 函数或 dispatch_async_f 函数
1.6 用GCD同步执行非UI相关的任务
目的:想要执行那些不包含任何UI相关代码的同步任务
方案:使用dispatch_sync 函数。
讨论:当执行那些与UI无关的任务,或者与UI交互任务时,和执行其他任务一样,会需要大量的时间,以上情况会经常出现。例如,你想下载一个图片并想在下载完成之后展现给用户。下载过程却和UI没有任何关系。
对于任何与UI无关的任务,你可以使用GCD中的全局并发队列。它们允许同步和异步执行。但是同步执行并不是说你的程序在继续之前要等到代码编程结束。这里是说并发队列会一直等待到你的任务完成后,才会再任务继续队列中的下一个代码块。
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);全局并发队列可以用同步和异步执行。
1.7 在GCD上异步执行非UI相关任务
目的:你想要在GCD的帮助下能够异步执行非UI相关任务。
方案:主队列、串行队列和并发队列上异步执行代码块才能见识到GCD的真正实力。(本书作者说,GCD会是多线程应用的未来,并将完全取代现代应用中的线程),千万注意:不要再主队列中使用同步执行函数dispatch_sync
要在分派队列上执行异步任务,你必须使用下面的这些函数中的其中一个:
dispatch_async 函数或者
dispatch_async_f 函数
我们来看个实例。我们来写一个iOS APP, 它能从网络的URL上下载一个图片。下载完成之后,APP应该将图片展示给用户。这个是我们的计划,那么为了达到这个目的我们该如何使用目前为止掌握的关于GCD的技能:
1、我们在并发队列上异步的启动一个block object。
2、在这个block中我们使用dispatch_sync函数来启动另一个Block Object,以从URL上下载图片。我这样做的目的是想让并发队列中剩余的代码能够等到图片下载完成之后在继续执行。从一个异步代码块上同步下载一个URL可以保持这个队列运行同步函数,而不是主线程。当我们从主线程角度来看的话整个运作仍是异步的。我们关心的问题是在下载图片的过程中没有阻塞主线程。
3、图片下载完毕后,为了在UI上将图片展示给用户,我们会在主线程上同步执行一个Block Object(见6.5)。
我们计划的框架就是这么简单:
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_async(concurrentQueue, ^{ __block UIImage *image = nil; dispatch_sync(concurrentQueue, ^{ /* Download the image here */ }); dispatch_sync(dispatch_get_main_queue(), ^{ /* Show the image to the user here on the main queue*/ }); });
在第一个下载图片的同步调用结束之后,第二个dispatch_sync调用会在队列中执行,这个调用负责展示图片;这就是我们确切需要的东西,因为在图片展示给用户之前我们必须等图片完全下载。所以在图片下载完成之后,我们执行第二个Block Object,但这一次是在主队列上。
我们现在来下载图片并将其展示给用户。我们将通过iPhone App的一个视图控制器的viewDidAppear:方法来实现:
-(void)viewDidAppear:(BOOL)animated{ //在GCD上异步执行非UI相关任务 dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_async(concurrentQueue, ^{ __block UIImage *image = nil; dispatch_sync(concurrentQueue, ^{ /*download the image here*/ NSString *urlString = @"http://cms.csdnimg.cn/article/201310/09/5254b7b6c74cb.jpg"; NSURL *url = [NSURL URLWithString:urlString]; NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url]; NSError *downloadError = nil; NSData *imageData = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:nil error:&downloadError]; if (downloadError == nil && imageData != nil) { image = [UIImage imageWithData:imageData]; } else if(downloadError != nil){ NSLog(@"Error happened = %@",downloadError); } else{ NSLog(@"No data could get download from the URL"); } }); dispatch_sync(dispatch_get_main_queue(), ^{ /*show the image to the user here on the main queue*/ if(image != nil){ //create the image view here UIImageView *imageView = [[UIImageView alloc] initWithFrame:self.view.bounds]; [imageView setImage:image]; /* make sure the image is not scaled incorrectly */ [imageView setContentMode:UIViewContentModeScaleAspectFit]; /* add the image to this view controller's view */ [self.view addSubview:imageView]; } else{ NSLog(@"Image isn't downloaded.NOthing to display"); } }); }); }
运行结果如下:
在unity3d中,如果我们我们需要系统同一套使用igui制作的GUI系统怎么办呢?如果我们直接在原来的场景中
拷贝一份是可以,但是呢!当我们编写逻辑代码的时候就会在原来的IGUICode_xx.cs文件进行编辑的。这样就会出现。大家都不希望看到的现象,那就是影响以前的代码结构。这样带来很多心的BUG,同时代码就变得更加复杂了!
所以我们就需要对原来的iguiCode_xx.cs文件进行重命名,同时使用iGUIRoot对象上的Manual Code File属性进行设置,这样就可以达到我们需要的效果了,既实现了代码的重用也不会导致代码的冗余高的现象了!想想挺爽的!!
现在介绍如下:
1、我们重命名一下原来的iGUICode_xx.cs文件命名(EG: iGUICode_demo.cs——>iGUICode_test.cs)
2、我们接下来需要把iGUICode_test.cs文件中的类名字以及相关的变量类型改为iGUICode_test
(我们可以使用monoIDE中的反射进行)
3、最后我们把改好的cs文件拖给iGUIRoot对象上的Manual Code File属性,同时删除原来丢失的文件
效果图:
结束语:
完成上面的步骤,我们需要的效果就有了!
Enjoy!
参考:http://wiki.cyanogenmod.org/w/Build_for_i9300
安装相关库。如git, open sdk, python等;
安装android sdk,需要连接手机获取一些文件,而且手机必需刷cm-10.2的rom.
http://developer.android.com/sdk/index.html
安装android sdk 解压android sdk后修改
sudo gedit /etc/hosts/
74.125.237.1 dl-ssl.google.com
执行tool/android update sdk更新后就有platform-tools目录和adb了,执行adb devices查看设备是否已经连接, 下一个cm的rom刷入http://get.cm/?device=i9300 版本和你编译版本一致。
1. 不要使用Ubuntu 12.04 32位,太吭了,搞了大半月没有搞定,无耐换装64位系统,1天搞定了。
注意32位下载的代码不要全删掉,把.repo目录压缩一下,大概9G左右,放到windows分区去。再装64位系统,
64位系统安装好后,新建一个目录如cm-10.2, 执行
附件提供了repo, 可以googlecode下载repo 1.19的版本。
repo init -u git://github.com/CyanogenMod/android.git -b cm-10.2
repo sync
ctrl+x 停掉repo sync, 再把原来备份的.repo/project目录覆盖到cm-10.2/.repo/project目录,这样基本就不用再下以前的代码了,会30分钟左右就下完代码,应该不是下完,repo好像是从.repo/project目录复制到外边cm-10.2目录下,坑人么,搞两份代码。
2. Ubuntu12.04基本上要留50个磁盘空间,分区大概如下:
/swap 交换分区2G(和你的内存大小一样)、
/ 根分区安装系统 大概留8G左右,最小5G,不过还是留大点好防止系统分区太小
/home home分区,剩下全留全home分区,主要为编译,我剩下的就45G左右
我的分区情况, 代码同步完成后:
Filesystem Size Used Avail Use% Mounted on /dev/sda9 7.4G 4.4G 2.7G 63% / udev 993M 4.0K 993M 1% /dev tmpfs 401M 916K 400M 1% /run none 5.0M 0 5.0M 0% /run/lock none 1002M 156K 1002M 1% /run/shm /dev/sda10 45G 21G 22G 48% /home
编译完成后:
wv@wv-ThinkPad-SL:~$ df -h Filesystem Size Used Avail Use% Mounted on /dev/sda9 7.4G 4.4G 2.7G 63% / udev 993M 4.0K 993M 1% /dev tmpfs 401M 908K 400M 1% /run none 5.0M 0 5.0M 0% /run/lock none 1002M 156K 1002M 1% /run/shm /dev/sda10 45G 36G 6.5G 85% /home wv@wv-ThinkPad-SL:~$
3. 编译过程中:
repo init -u git://github.com/CyanogenMod/android.git -b cm-10.2
repo sync
cd cm-10.2/vendor/cm
./get-prebuilts //(这一步是为了下载Term.apk并解压到当前propritary目录) (只需执行一次,以后编译无需执行)
cd ../..
source build/envsetup.sh
breakfast i9300
//(这一步会自动从github下载 三星I897[代号captivatemtd]设备的驱动和内核; 注意 必须是CM官方支持升级到cm10.1的设备才能使用这个命令下载到//内核和驱动!!!) (只需执行一次,以后编译无需执行)
这步会报错, 因为找不到device i9300
直接到
https://github.com/CyanogenMod/android_device_samsung_i9300
https://github.com/CyanogenMod/android_device_samsung_smdk4412-common
下载后解压到 cm-10.2/device/samsung/i9300和cm-10.2/device/samsung/smdk4412-common
其它设备可以参考
https://github.com/CyanogenMod/android_device_samsung_设备名 从github上下载。
手机上刷9300 cm10.2的rom 并连接上手机,之前要安装androis sdk,
cd cm-10.2/device/samsung/i9300
chmod a+x extract-files.sh
./extract-files.sh // (这条命令实际上都是组织好的的adb pull,它将真机中的部分库和依赖文件拷贝到本地源码环境,辅助编译!因为部分库和依赖文件的源码我们无法获取,
//相关厂商只提供了这些编译好的东东!这一部很重要,如果跳过,即时编译ROM成功,刷机后手机也跑不起来的!) (只需执行一次,以后编译无需执行)
说明: 如果你不想预先把手机刷成CM10.1,可以以文本打开extract-files.sh,就看到里面其实都是拷贝文件的操作。那么你解压从官方获取的cm10.1的rom压缩包,逐个拷贝相应文件到源码环境相应目录,并编辑相应目录的mk文件,加入 "PRODCUT_COPY_FILES + =..." 这样的语句也是可以的,但是很麻烦!
croot
brunch i9300
开始真正的编译,编译过程中没有出现任何问题,大概4个小时左右编译完成。
mon.Partition object at 0x29f2710>} fstab_version = (int) 2 mkbootimg_args = (str) mkyaffs2_extra_flags = (str) -c 4096 -s 128 recovery_api_version = (int) 2 recovery_size = (int) 8388608 selinux_fc = (str) /tmp/targetfiles-corf9Q/BOOT/RAMDISK/file_contexts system_size = (int) 1610612736 tool_extensions = (str) device/samsung/i9300/../common userdata_size = (int) 12381585408 using device-specific extensions in device/samsung/common unable to load device-specific module; assuming none building image from target_files BOOT... running: mkbootfs -f /tmp/targetfiles-corf9Q/META/boot_filesystem_config.txt /tmp/targetfiles-corf9Q/BOOT/RAMDISK running: minigzip running: mkbootimg --kernel /tmp/targetfiles-corf9Q/BOOT/kernel --cmdline console=ttySAC2,115200 --base 0x40000000 --pagesize 2048 --ramdisk /tmp/tmpktqmNH --output /tmp/tmp33v1T7 running: openssl pkcs8 -in build/target/product/security/testkey.pk8 -inform DER -nocrypt running: java -Xmx2048m -jar /home/wv/source/android/cm-10.2/out/host/linux-x86/framework/signapk.jar -w build/target/product/security/testkey.x509.pem build/target/product/security/testkey.pk8 /tmp/tmpdhEqjX /home/wv/source/android/cm-10.2/out/target/product/i9300/cm_i9300-ota-eng.wv.zip done. Package Complete: /home/wv/source/android/cm-10.2/out/target/product/i9300/cm-10.2-20130921-UNOFFICIAL-i9300.zip wv@wv-ThinkPad-SL:~/source/android/cm-10.2$
可以看到编译后包!
cm-10.2/out/target/product/i9300/cm-10.2-20130921-UNOFFICIAL-i9300.zip
参考:
http://www.cnblogs.com/tomsen/archive/2013/06/04/3115460.html
http://wiki.cyanogenmod.org/w/Build_for_i9300
*****************************************************************************************
Other:
https://gerrit.googlesource.com/git-repo/clone.bundle
curl https://dl-ssl.google.com/dl/googlesource/git-repo/repo ~/bin/repo
repo init -u git://github.com/CyanogenMod/android.git -b cm-10.2
sudo ~/bin/repo init -u https://github.com/CyanogenMod/android.git -b cm-10.2
~/ext-3/android/bin/repo sync -fj16
http://www.360doc.com/content/10/0221/10/155970_16310464.shtml
make:进入目录'/home/wv/android/cm-10.2'
make: *** 没有规则可以创建“out/target/product/generic/obj/EXECUTABLES/netd_intermediates/LINKED/netd”需要的目标“out/target/product/generic/obj/lib/crtbegin_dynamic.o”。 停止。
make:离开目录“/home/wv/android/cm-10.2”