Android应用程序发送广播(sendBroadcast)的过程分析(2)

简介:
    继续往下看:
 
 
  1. final boolean replacePending =   
  2.   (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;   
       这里是查看一下这个intent的Intent.FLAG_RECEIVER_REPLACE_PENDING位有没有设置,如果设置了的话,ActivityManagerService就会在当前的系统中查看有没有相同的intent还未被处理,如果有的话,就有当前这个新的intent来替换旧的intent。这里,我们没有设置intent的Intent.FLAG_RECEIVER_REPLACE_PENDING位,因此,这里的replacePending变量为false。
       再接着往下看:
 
 
  1.  int NR = registeredReceivers != null ? registeredReceivers.size() : 0;   
  2.   if (!ordered && NR > 0) {   
  3. // If we are not serializing this broadcast, then send the   
  4. // registered receivers separately so they don't wait for the   
  5. // components to be launched.   
  6. BroadcastRecord r = new BroadcastRecord(intent, callerApp,   
  7.     callerPackage, callingPid, callingUid, requiredPermission,   
  8.     registeredReceivers, resultTo, resultCode, resultData, map,   
  9.     ordered, sticky, false);   
  10. ......   
  11. boolean replaced = false;   
  12. if (replacePending) {   
  13.     for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {   
  14.         if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {   
  15.             ......   
  16.             mParallelBroadcasts.set(i, r);   
  17.             replaced = true;   
  18.             break;   
  19.         }   
  20.     }   
  21. }   
  22.    
  23. if (!replaced) {   
  24.     mParallelBroadcasts.add(r);   
  25.    
  26.     scheduleBroadcastsLocked();   
  27. }   
  28.    
  29. registeredReceivers = null;   
  30. NR = 0;   
  31.    }   
 
        前面我们说到,这里得到的列表registeredReceivers的大小为1,且传进来的参数ordered为false,表示要将这个广播发送给所有注册了BROADCAST_COUNTER_ACTION类型广播的接收器,因此,会执行下面的if语句。这个if语句首先创建一个广播记录块BroadcastRecord,里面记录了这个广播是由谁发出的以及要发给谁等相关信息。由于前面得到的replacePending变量为false,因此,不会执行接下来的if语句,即不会检查系统中是否有相同类型的未处理的广播。
 
        这样,这里得到的replaced变量的值也为false,于是,就会把这个广播记录块r放在ActivityManagerService的成员变量mParcelBroadcasts中,等待进一步处理;进一步处理的操作由函数scheduleBroadcastsLocked进行。
        Step 6. ActivityManagerService.scheduleBroadcastsLocked
        这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:
 
 
  1. public final class ActivityManagerService extends ActivityManagerNative   
  2.         implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {   
  3.     ......   
  4.    
  5.     private final void scheduleBroadcastsLocked() {   
  6.         ......   
  7.    
  8.         if (mBroadcastsScheduled) {   
  9.             return;   
  10.         }   
  11.    
  12.         mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);   
  13.         mBroadcastsScheduled = true;   
  14.     }   
  15.    
  16.     ......   
  17. }   
 
        这里的mBroadcastsScheduled表示ActivityManagerService当前是不是正在处理其它广播,如果是的话,这里就先不处理直接返回了,保证所有广播串行处理。
 
        注意这里处理广播的方式,它是通过消息循环来处理,每当ActivityManagerService接收到一个广播时,它就把这个广播放进自己的消息队列去就完事了,根本不管这个广播后续是处理的,因此,这里我们可以看出广播的发送和处理是异步的。
        这里的成员变量mHandler是一个在ActivityManagerService内部定义的Handler类变量,通过它的sendEmptyMessage函数把一个类型为BROADCAST_INTENT_MSG的空消息放进ActivityManagerService的消息队列中去。这里的空消息是指这个消息除了有类型信息之外,没有任何其它额外的信息,因为前面已经把要处理的广播信息都保存在mParcelBroadcasts中了,等处理这个消息时,从mParcelBroadcasts就可以读回相关的广播信息了,因此,这里不需要把广播信息再放在消息内容中。
        Step 7. Handler.sendEmptyMessage
        这个自定义的Handler类实现在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中,它是ActivityManagerService的内部类,调用了它的sendEmptyMessage函数来把一个消息放到消息队列后,一会就会调用它的handleMessage函数来真正处理这个消息:
 
 
  1. public final class ActivityManagerService extends ActivityManagerNative   
  2.         implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {   
  3.     ......   
  4.    
  5.     final Handler mHandler = new Handler() {   
  6.         public void handleMessage(Message msg) {   
  7.             switch (msg.what) {   
  8.             ......   
  9.             case BROADCAST_INTENT_MSG: {   
  10.                 ......   
  11.                 processNextBroadcast(true);   
  12.             } break;   
  13.             ......   
  14.             }   
  15.         }   
  16.     }   
  17.    
  18.     ......   
  19. }    
 
        这里又调用了ActivityManagerService的processNextBroadcast函数来处理下一个未处理的广播。
 
        Step 8. ActivityManagerService.processNextBroadcast
        这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:
 
 
  1. public final class ActivityManagerService extends ActivityManagerNative   
  2.         implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {   
  3.     ......   
  4.    
  5.     private final void processNextBroadcast(boolean fromMsg) {   
  6.         synchronized(this) {   
  7.             BroadcastRecord r;   
  8.    
  9.             ......   
  10.    
  11.             if (fromMsg) {   
  12.                 mBroadcastsScheduled = false;   
  13.             }   
  14.    
  15.             // First, deliver any non-serialized broadcasts right away.   
  16.             while (mParallelBroadcasts.size() > 0) {   
  17.                 r = mParallelBroadcasts.remove(0);   
  18.                 ......   
  19.                 final int N = r.receivers.size();   
  20.                 ......   
  21.                 for (int i=0; i<N; i++) {   
  22.                     Object target = r.receivers.get(i);   
  23.                     ......   
  24.    
  25.                     deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);   
  26.                 }   
  27.                 addBroadcastToHistoryLocked(r);   
  28.                 ......   
  29.             }   
  30.    
  31.             ......   
  32.    
  33.         }   
  34.     }   
  35.    
  36.     ......   
  37. }   
 
       这里传进来的参数fromMsg为true,于是把mBroadcastScheduled重新设为false,这样,下一个广播就能进入到消息队列中进行处理了。前面我们在Step 5中,把一个广播记录块BroadcastRecord放在了mParallelBroadcasts中,因此,这里就把它取出来进行处理了。广播记录块BroadcastRecord的receivers列表中包含了要接收这个广播的目标列表,即前面我们注册的广播接收器,用BroadcastFilter来表示,这里while循环中的for循环就是把这个广播发送给每一个订阅了该广播的接收器了,通过deliverToRegisteredReceiverLocked函数执行。
 
        Step 9. ActivityManagerService.deliverToRegisteredReceiverLocked
        这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:
 
 
  1. public final class ActivityManagerService extends ActivityManagerNative   
  2.         implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {   
  3.     ......   
  4.    
  5.     private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,   
  6.             BroadcastFilter filter, boolean ordered) {   
  7.         boolean skip = false;   
  8.         if (filter.requiredPermission != null) {   
  9.             ......   
  10.         }   
  11.         if (r.requiredPermission != null) {   
  12.             ......   
  13.         }   
  14.    
  15.         if (!skip) {   
  16.             // If this is not being sent as an ordered broadcast, then we   
  17.             // don't want to touch the fields that keep track of the current   
  18.             // state of ordered broadcasts.   
  19.             if (ordered) {   
  20.                 ......   
  21.             }   
  22.    
  23.             try {   
  24.                 ......   
  25.                 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,   
  26.                     new Intent(r.intent), r.resultCode,   
  27.                     r.resultData, r.resultExtras, r.ordered, r.initialSticky);   
  28.                 ......   
  29.             } catch (RemoteException e) {   
  30.                 ......   
  31.             }   
  32.         }   
  33.    
  34.     }   
  35.    
  36.     ......   
  37. }   
 
         函数首先是检查一下广播发送和接收的权限,在我们分析的这个场景中,没有设置权限,因此,这个权限检查就跳过了,这里得到的skip为false,于是进入下面的if语句中。由于上面传时来的ordered参数为false,因此,直接就调用performReceiveLocked函数来进一步执行广播发送的操作了。
 
        Step 10. ActivityManagerService.performReceiveLocked
        这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:
 
 
  1. public final class ActivityManagerService extends ActivityManagerNative   
  2.         implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {   
  3.     ......   
  4.    
  5.     static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,   
  6.             Intent intent, int resultCode, String data, Bundle extras,   
  7.             boolean ordered, boolean sticky) throws RemoteException {   
  8.         // Send the intent to the receiver asynchronously using one-way binder calls.   
  9.         if (app != null && app.thread != null) {   
  10.             // If we have an app thread, do the call through that so it is   
  11.             // correctly ordered with other one-way calls.   
  12.             app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,   
  13.                     data, extras, ordered, sticky);   
  14.         } else {   
  15.             ......   
  16.         }   
  17.     }   
  18.    
  19.     ......   
  20. }   
 
        注意,这里传进来的参数app是注册广播接收器的Activity所在的进程记录块,在我们分析的这个场景中,由于是MainActivity调用registerReceiver函数来注册这个广播接收器的,因此,参数app所代表的ProcessRecord就是MainActivity所在的进程记录块了;而参数receiver也是注册广播接收器时传给ActivityManagerService的一个Binder对象,它的类型是IIntentReceiver,具体可以参考上一篇文章 Android应用程序注册广播接收器(registerReceiver)的过程分析 中的Step 2。
 
       MainActivity在注册广播接收器时,已经把自己的ProcessRecord记录下来了,所以这里的参数app和app.thread均不为null,于是,ActivityManagerService就调用app.thread.scheduleRegisteredReceiver函数来把这个广播分发给MainActivity了。这里的app.thread是一个Binder远程对象,它的类型是ApplicationThreadProxy,我们在前面介绍应用程序的Activity启动过程时,已经多次看到了,具体可以参考主题 Android应用程序的Activity启动过程简要介绍和学习计划
       Step 11. ApplicationThreadProxy.scheduleRegisteredReceiver
       这个函数定义在frameworks/base/core/java/android/app/ApplicationThreadNative.java文件中:
 
 
  1. class ApplicationThreadProxy implements IApplicationThread {   
  2.     ......   
  3.    
  4.     public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,   
  5.             int resultCode, String dataStr, Bundle extras, boolean ordered, boolean sticky)   
  6.             throws RemoteException {   
  7.         Parcel data = Parcel.obtain();   
  8.         data.writeInterfaceToken(IApplicationThread.descriptor);   
  9.         data.writeStrongBinder(receiver.asBinder());   
  10.         intent.writeToParcel(data, 0);   
  11.         data.writeInt(resultCode);   
  12.         data.writeString(dataStr);   
  13.         data.writeBundle(extras);   
  14.         data.writeInt(ordered ? 1 : 0);   
  15.         data.writeInt(sticky ? 1 : 0);   
  16.         mRemote.transact(SCHEDULE_REGISTERED_RECEIVER_TRANSACTION, data, null,   
  17.             IBinder.FLAG_ONEWAY);   
  18.         data.recycle();   
  19.     }   
  20.    
  21.     ......   
  22. }   
 
        这里通过Binder驱动程序就进入到ApplicationThread.scheduleRegisteredReceiver函数去了。ApplicationThread是ActivityThread的一个内部类,具体可以参考Activity启动主题 Android应用程序的Activity启动过程简要介绍和学习计划
 
        Step 12. ApplicaitonThread.scheduleRegisteredReceiver
        这个函数定义在frameworks/base/core/java/android/app/ActivityThread.java文件中:
 
 
  1. public final class ActivityThread {   
  2.     ......   
  3.    
  4.     private final class ApplicationThread extends ApplicationThreadNative {   
  5.         ......   
  6.    
  7.         // This function exists to make sure all receiver dispatching is   
  8.         // correctly ordered, since these are one-way calls and the binder driver   
  9.         // applies transaction ordering per object for such calls.   
  10.         public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,   
  11.                 int resultCode, String dataStr, Bundle extras, boolean ordered,   
  12.                 boolean sticky) throws RemoteException {   
  13.             receiver.performReceive(intent, resultCode, dataStr, extras, ordered, sticky);   
  14.         }   
  15.    
  16.         ......   
  17.     }   
  18.    
  19.     ......   
  20.    
  21. }   
 
        这里的receiver是在前面一篇文章 Android应用程序注册广播接收器(registerReceiver)的过程分析 中的Step 4中创建的,它的具体类型是LoadedApk.ReceiverDispatcher.InnerReceiver,即定义在LoadedApk类的内部类ReceiverDispatcher里面的一个内部类InnerReceiver,这里调用它的performReceive函数。
 
        Step 13. InnerReceiver.performReceive
        这个函数定义在frameworks/base/core/java/android/app/LoadedApk.java文件中:
 
 
  1. final class LoadedApk {     
  2.     ......    
  3.    
  4.     static final class ReceiverDispatcher {     
  5.    
  6.         final static class InnerReceiver extends IIntentReceiver.Stub {    
  7.             ......   
  8.    
  9.             public void performReceive(Intent intent, int resultCode,   
  10.                     String data, Bundle extras, boolean ordered, boolean sticky) {   
  11.                
  12.                 LoadedApk.ReceiverDispatcher rd = mDispatcher.get();   
  13.                 ......   
  14.                 if (rd != null) {   
  15.                     rd.performReceive(intent, resultCode, data, extras,   
  16.                             ordered, sticky);   
  17.                 } else {   
  18.                     ......   
  19.                 }   
  20.             }   
  21.         }   
  22.    
  23.         ......   
  24.     }   
  25.    
  26.     ......   
  27. }   
 
         这里,它只是简单地调用ReceiverDispatcher的performReceive函数来进一步处理,这里的ReceiverDispatcher类是LoadedApk类里面的一个内部类。
 
         Step 14. ReceiverDispatcher.performReceive
         这个函数定义在frameworks/base/core/java/android/app/LoadedApk.java文件中:
 
  
  1. final class LoadedApk {     
  2.     ......    
  3.    
  4.     static final class ReceiverDispatcher {     
  5.         ......   
  6.    
  7.         public void performReceive(Intent intent, int resultCode,   
  8.                 String data, Bundle extras, boolean ordered, boolean sticky) {   
  9.             ......   
  10.    
  11.             Args args = new Args();   
  12.             args.mCurIntent = intent;   
  13.             args.mCurCode = resultCode;   
  14.             args.mCurData = data;   
  15.             args.mCurMap = extras;   
  16.             args.mCurOrdered = ordered;   
  17.             args.mCurSticky = sticky;   
  18.             if (!mActivityThread.post(args)) {   
  19.                 ......   
  20.             }    
  21.         }   
  22.    
  23.         ......   
  24.     }   
  25.    
  26.     ......   
  27. }   
 
        这里mActivityThread成员变量的类型为Handler,它是前面MainActivity注册广播接收器时,从ActivityThread取得的,具体可以参考前面一篇文章 Android应用程序注册广播接收器(registerReceiver)的过程分析 中的Step 3。这里ReceiverDispatcher借助这个Handler,把这个广播以消息的形式放到MainActivity所在的这个ActivityThread的消息队列中去,因此,ReceiverDispatcher不等这个广播被MainActivity处理就返回了,这里也体现了广播的发送和处理是异步进行的。
 
        注意这里处理消息的方式是通过Handler.post函数进行的,post函数的参数是Runnable类型的,这个消息最终会调用这个这个参数的run成员函数来处理。这里的Args类是LoadedApk类的内部类ReceiverDispatcher的一个内部类,它继承于Runnable类,因此,可以作为mActivityThread.post的参数传进去,代表这个广播的intent也保存在这个Args实例中。
        Step 15. Hanlder.post
        这个函数定义在frameworks/base/core/java/android/os/Handler.java文件中,这个函数我们就不看了,有兴趣的读者可以自己研究一下,它的作用就是把消息放在消息队列中,然后就返回了,这个消息最终会在传进来的Runnable类型的参数的run成员函数中进行处理。
        Step 16. Args.run
        这个函数定义在frameworks/base/core/java/android/app/LoadedApk.java文件中:
 
  
  1. final class LoadedApk {     
  2.     ......    
  3.    
  4.     static final class ReceiverDispatcher {   
  5.         ......   
  6.    
  7.         final class Args implements Runnable {   
  8.             ......   
  9.    
  10.             public void run() {   
  11.                 BroadcastReceiver receiver = mReceiver;   
  12.    
  13.                 ......   
  14.    
  15.                 Intent intent = mCurIntent;   
  16.                    
  17.                 ......   
  18.    
  19.                 try {   
  20.                     ClassLoader cl =  mReceiver.getClass().getClassLoader();   
  21.                     intent.setExtrasClassLoader(cl);   
  22.                     if (mCurMap != null) {   
  23.                         mCurMap.setClassLoader(cl);   
  24.                     }   
  25.                     receiver.setOrderedHint(true);   
  26.                     receiver.setResult(mCurCode, mCurData, mCurMap);   
  27.                     receiver.clearAbortBroadcast();   
  28.                     receiver.setOrderedHint(mCurOrdered);   
  29.                     receiver.setInitialStickyHint(mCurSticky);   
  30.                     receiver.onReceive(mContext, intent);   
  31.                 } catch (Exception e) {   
  32.                     ......   
  33.                 }   
  34.    
  35.                 ......   
  36.             }   
  37.    
  38.             ......   
  39.         }   
  40.    
  41.         ......   
  42.     }   
  43.    
  44.     ......   
  45. }   
       这里的mReceiver是ReceiverDispatcher类的成员变量,它的类型是BroadcastReceiver,这里它就是MainActivity注册广播接收器时创建的BroadcastReceiver实例了,具体可以参考前面一篇文章 Android应用程序注册广播接收器(registerReceiver)的过程分析 中的Step 2。
 
        有了这个ReceiverDispatcher实例之后,就可以调用它的onReceive函数把这个广播分发给它处理了。
        Step 17. BroadcastReceiver.onReceive
        这个函数定义 Android系统中的广播(Broadcast)机制简要介绍和学习计划一文中所介绍的Android应用程序Broadcast的工程目录下的src/shy/luo/broadcast/MainActivity.java文件中:
 
  
  1. public class MainActivity extends Activity implements OnClickListener {       
  2.     ......     
  3.    
  4.     private BroadcastReceiver counterActionReceiver = new BroadcastReceiver(){     
  5.         public void onReceive(Context context, Intent intent) {     
  6.             int counter = intent.getIntExtra(CounterService.COUNTER_VALUE, 0);     
  7.             String text = String.valueOf(counter);     
  8.             counterText.setText(text);     
  9.    
  10.             Log.i(LOG_TAG, "Receive counter event");     
  11.         }       
  12.     }   
  13.    
  14.     ......     
  15.    
  16. }   
        这样,MainActivity里面的定义的BroadcastReceiver实例counterActionReceiver就收到这个广播并进行处理了。
        至此,Android应用程序发送广播的过程就分析完成了,结合前面这篇分析广播接收器注册过程的文章 Android应用程序注册广播接收器(registerReceiver)的过程分析 ,就会对Android系统的广播机制且个更深刻的认识和理解了。
 
        最后,我们总结一下这个Android应用程序发送广播的过程:
        1. Step 1 - Step 7,计数器服务CounterService通过sendBroadcast把一个广播通过Binder进程间通信机制发送给ActivityManagerService,ActivityManagerService根据这个广播的Action类型找到相应的广播接收器,然后把这个广播放进自己的消息队列中去,就完成第一阶段对这个广播的异步分发了;
        2. Step 8 - Step 15,ActivityManagerService在消息循环中处理这个广播,并通过Binder进程间通信机制把这个广播分发给注册的广播接收分发器ReceiverDispatcher,ReceiverDispatcher把这个广播放进MainActivity所在的线程的消息队列中去,就完成第二阶段对这个广播的异步分发了;
        3. Step 16 - Step 17, ReceiverDispatcher的内部类Args在MainActivity所在的线程消息循环中处理这个广播,最终是将这个广播分发给所注册的BroadcastReceiver实例的onReceive函数进行处理。
        这样,Android系统广播机制就学习完成了,希望对读者有所帮助。重新学习Android系统的广播机制,请回到 Android系统中的广播(Broadcast)机制简要介绍和学习计划一文中。





本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/966399,如需转载请自行联系原作者

目录
相关文章
|
4天前
|
安全 Android开发 数据安全/隐私保护
深入探讨iOS与Android系统安全性对比分析
在移动操作系统领域,iOS和Android无疑是两大巨头。本文从技术角度出发,对这两个系统的架构、安全机制以及用户隐私保护等方面进行了详细的比较分析。通过深入探讨,我们旨在揭示两个系统在安全性方面的差异,并为用户提供一些实用的安全建议。
|
12天前
|
缓存 Java Shell
Android 系统缓存扫描与清理方法分析
Android 系统缓存从原理探索到实现。
38 15
Android 系统缓存扫描与清理方法分析
|
3天前
|
JSON Java Android开发
探索安卓开发之旅:打造你的第一个天气应用
【10月更文挑战第30天】在这个数字时代,掌握移动应用开发技能无疑是进入IT行业的敲门砖。本文将引导你开启安卓开发的奇妙之旅,通过构建一个简易的天气应用来实践你的编程技能。无论你是初学者还是有一定经验的开发者,这篇文章都将成为你宝贵的学习资源。我们将一步步地深入到安卓开发的世界中,从搭建开发环境到实现核心功能,每个环节都充满了发现和创造的乐趣。让我们开始吧,一起在代码的海洋中航行!
|
4天前
|
存储 搜索推荐 Java
打造个性化安卓应用:从设计到实现
【10月更文挑战第30天】在数字化时代,拥有一个个性化的安卓应用不仅能够提升用户体验,还能加强品牌识别度。本文将引导您了解如何从零开始设计和实现一个安卓应用,涵盖用户界面设计、功能开发和性能优化等关键环节。我们将以一个简单的记事本应用为例,展示如何通过Android Studio工具和Java语言实现基本功能,同时确保应用流畅运行。无论您是初学者还是希望提升现有技能的开发者,这篇文章都将为您提供宝贵的见解和实用的技巧。
|
7天前
|
搜索推荐 开发工具 Android开发
打造个性化Android应用:从设计到实现的旅程
【10月更文挑战第26天】在这个数字时代,拥有一个能够脱颖而出的移动应用是成功的关键。本文将引导您了解如何从概念化阶段出发,通过设计、开发直至发布,一步步构建一个既美观又实用的Android应用。我们将探讨用户体验(UX)设计的重要性,介绍Android开发的核心组件,并通过实际案例展示如何克服开发中的挑战。无论您是初学者还是有经验的开发者,这篇文章都将为您提供宝贵的见解和实用的技巧,帮助您在竞争激烈的应用市场中脱颖而出。
|
9天前
|
算法 Java 数据库
Android 应用的主线程在什么情况下会被阻塞?
【10月更文挑战第20天】为了避免主线程阻塞,我们需要合理地设计和优化应用的代码。将耗时操作移到后台线程执行,使用异步任务、线程池等技术来提高应用的并发处理能力。同时,要注意避免出现死循环、不合理的锁使用等问题。通过这些措施,可以确保主线程能够高效地运行,提供流畅的用户体验。
21 2
|
13天前
|
Java API Android开发
安卓应用程序开发的新手指南:从零开始构建你的第一个应用
【10月更文挑战第20天】在这个数字技术不断进步的时代,掌握移动应用开发技能无疑打开了一扇通往创新世界的大门。对于初学者来说,了解并学习如何从无到有构建一个安卓应用是至关重要的第一步。本文将为你提供一份详尽的入门指南,帮助你理解安卓开发的基础知识,并通过实际示例引导你完成第一个简单的应用项目。无论你是编程新手还是希望扩展你的技能集,这份指南都将是你宝贵的资源。
42 5
|
13天前
|
移动开发 Dart 搜索推荐
打造个性化安卓应用:从零开始的Flutter之旅
【10月更文挑战第20天】本文将引导你开启Flutter开发之旅,通过简单易懂的语言和步骤,让你了解如何从零开始构建一个安卓应用。我们将一起探索Flutter的魅力,实现快速开发,并见证代码示例如何生动地转化为用户界面。无论你是编程新手还是希望扩展技能的开发者,这篇文章都将为你提供价值。
|
23天前
|
调度 Android开发 开发者
构建高效Android应用:探究Kotlin多线程优化策略
【10月更文挑战第11天】本文探讨了如何在Kotlin中实现高效的多线程方案,特别是在Android应用开发中。通过介绍Kotlin协程的基础知识、异步数据加载的实际案例,以及合理使用不同调度器的方法,帮助开发者提升应用性能和用户体验。
40 4
|
23天前
|
编解码 Android开发 UED
构建高效Android应用:从内存优化到用户体验
【10月更文挑战第11天】本文探讨了如何通过内存优化和用户体验改进来构建高效的Android应用。介绍了使用弱引用来减少内存占用、懒加载资源以降低启动时内存消耗、利用Kotlin协程进行异步处理以保持UI流畅,以及采用响应式设计适配不同屏幕尺寸等具体技术手段。
45 2