Android之常见面试题

http://blog.sina.com.cn/s/blog_4f1d20f30100v23r.html

最近想找找工作看,没想到第一次去面试ANDROID开发工程师就碰壁了,虽然说做了两年的手机开发了,可哥却没参加过一次ANDROID的面试,所以这次一定要汲取教训,面试

http://blog.sina.com.cn/s/blog_4f1d20f30100v23r.html

最近想找找工作看,没想到第一次去面试ANDROID开发工程师就碰壁了,虽然说做了两年的手机开发了,可哥却没参加过一次ANDROID的面试,所以这次一定要汲取教训,面试之前一定要看看面试题。
 
1. 请描述下Activity的生命周期。 
2. 如果后台的Activity由于某原因被系统回收了,如何在被系统回收之前保存当前状态? 
3. 如何将一个Activity设置成窗口的样式。(Edited by Sodino) 
4. 如何退出Activity?如何安全退出已调用多个Activity的Application? 
5. 请介绍下Android中常用的五种布局。 
6. 请介绍下Android的数据存储方式。(Edited by Sodino) 
7. 请介绍下ContentProvider是如何实现数据共享的。(Edited by Sodino) 
8. 如何启用Service,如何停用Service。(Edited by Sodino) 
9. 注册广播有几种方式,这些方式有何优缺点?请谈谈Android引入广播机制的用意。 
10. 请解释下在单线程模型中Message、Handler、Message Queue、Looper之间的关系。 
11. AIDL的全称是什么?如何工作?能处理哪些类型的数据? 
12. 请解释下Android程序运行时权限与文件系统权限的区别。(Edited by Sodino) 
13. 系统上安装了多种浏览器,能否指定某浏览器访问指定页面?请说明原由。 
14. 有一个一维整型数组int[]data保存的是一张宽为width,高为height的图片像素值信息。请写一个算法,将该图片所有的白色不透明(0xffffffff)像素点的透明度调整为50%。 
15. 你如何评价Android系统?优缺点。


1.请描述下Activity的生命周期
http://weizhulin.blog.51cto.com/1556324/311495
详细介绍一下这几个方法中系统在做什么以及我们应该做什么:

  onCreate:  在这里创建界面,做一些数据的初始化工作

  onStart:   到这一步变成用户可见不可交互 的

  onResume:  变成和用户可交互 的,(在activity栈系统通过栈的方式管理这些个      
                     Activity的最上面,运行完弹出栈,则回到上一个Activity)

  onPause:    到这一步是可见但不可交互 的,系统会停止动画 等消耗CPU 的事情
                   从上文的描述已经知道,应该在这里保存你的一些数据,因为这个时候
                   你的程序的优先级降低,有可能被系统收回。在这里保存的数据,应该在

                   onResume里读出来,注意:这个方法里做的事情时间要短,因为下一
                   个activity不会等到这个方法完成才启动

  onstop:    变得不可见 ,被下一个activity覆盖了

   onDestroy:这是activity被干掉前最后一个被调用方法了,可能是外面类调用finish方
                    法或者是系统为了节省空间将它暂时性的干掉,可以用isFinishing()来判
                    断它,如果你有一个Progress Dialog在线程中转动,请在onDestroy里
                    把他cancel掉,不然等线程结束的时候,调用Dialog的cancel方法会抛
                    异常的。

             
onPause,onstop, onDestroy,三种状态 下 activity都有可能被系统干掉
为了保证程序的正确性,你要在onPause()里写上持久层操作的代码,将用户编辑的内容都保存到存储介质上(一般都是数据库)。实际工作中因为生命周期的变化而带来的问题也很多,比如你的应用程序起了新的线程在跑,这时候中断了,你还要去维护那个线程,是暂停还是杀掉还是数据回滚,是吧?因为Activity可能被杀掉,所以线程中使用的变量和一些界面元素就千万要注意了,一般我都是采用Android的消息机制[Handler,Message]来处理多线程和界面交互的问题。这个我后面会讲一些,最近因为这些东西头已经很大了,等我理清思绪再跟大家分享。

 2. 如果后台的Activity由于某原因被系统回收了,如何在被系统回收之前保存当前状态?
当你的程序中某一个Activity A 在运行时中,主动或被动地运行另一个新的Activity B 这个时候A会执行

Java代码


 

  1. public 
  2. void onSaveInstanceState(Bundle outState)    
  3.     super.onSaveInstanceState(outState);    
  4.     outState.putLong("id", 1234567890);    
  5.    
  6.  
  7. public void onSaveInstanceState(Bundle outState)    super.onSaveInstanceState(outState);    outState.putLong("id", 1234567890);} 
  8.  


B 完成以后又会来找A, 这个时候就有两种情况,一种是A被回收,一种是没有被回收,被回
收的A就要重新调用onCreate()方法,不同于直接启动的是这回onCreate()里是带上参数
savedInstanceState,没被收回的就还是onResume就好了。

savedInstanceState是一个Bundle对象,你基本上可以把他理解为系统帮你维护的一个Map对象。在onCreate()里你可能会用到它,如果正常启动onCreate就不会有它,所以用的时候要判断一下是否为空。

Java代码


if(savedInstanceState !=null){  
    long id =savedInstanceState.getLong("id");  
 

if(savedInstanceState !=null){    long id = savedInstanceState.getLong("id");}


就像官方的Notepad教程里的情况,你正在编辑某一个note,突然被中断,那么就把这个note的id记住,再起来的时候就可以根据这个id去把那个note取出来,程序就完整一些。这也是看你的应用需不需要保存什么,比如你的界面就是读取一个列表,那就不需要特殊记住什么,哦,没准你需要记住滚动条的位置...

3. 如何将一个Activity设置成窗口的样式 
简单你只需要设置 一下Activity的主题就可以了在AndroidManifest.xml 中定义 Activity的
地方一句话:


Xml代码


 

  1. android :theme="@android:style/Theme.Dialog"  
  2.  
  3. android:theme="@android:style/Theme.Dialog"  
  4.  


这就使你的应用程序变成对话框的形式弹出来了,或者


Xml代码


 

  1. android:theme="@android:style/Theme.Translucent"  
  2.  
  3. android:theme="@android:style/Theme.Translucent"  
  4.  

就变成半透明的,[友情提示-.-]类似的这种activity的属性可以在android.R.styleable类的AndroidManifestActivity方法中看到,AndroidManifest.xml中所有元素的属性的介绍都可以参考这个类android.R.styleable

上面说的是属性名称,具体有什么值是在android.R.style中可以看到,比如这个"@android:style/Theme.Dialog"就对应于android.R.style.Theme_Dialog ,('_'换成'.'<--注意:这个是文章内容不是笑脸)就可以用在描述文件中了,找找类定义和描述文件中的对应关系就都明白了。


4. 如何退出Activity
对于单一Activity的应用来说,退出很简单,直接finish()即可。
当然,也可以用killProcess()和System.exit()这样的方法。现提供几个方法,供参考:

1、抛异常强制退出:
该方法通过抛异常,使程序Force Close。
验证可以,但是,需要解决的问题是,如何使程序结束掉,而不弹出Force Close的窗口。

2、记录打开的Activity:
每打开一个Activity,就记录下来。在需要退出时,关闭每一个Activity即可。

3、发送特定广播:
在需要结束应用时,发送一个特定的广播,每个Activity收到广播后,关闭即可。

4、递归退出
在打开新的Activity时使用startActivityForResult,然后自己加标志,在onActivityResult中处理,递归关闭。

除了第一个,都是想办法把每一个Activity都结束掉,间接达到目的。
但是这样做同样不完美。
你会发现,如果自己的应用程序对每一个Activity都设置了nosensor,在两个Activity结束的间隙,sensor可能有效了。
但至少,我们的目的达到了,而且没有影响用户使用。

为了编程方便,最好定义一个Activity基类,处理这些共通问题。5.请介绍下Android中常用的五种布局 Android布局是应用界面开发的重要一环,在Android中,共有五种布局方式,分别是:FrameLayout(框架布 局),LinearLayout (线性布局),AbsoluteLayout(绝对布局),RelativeLayout(相对布局),TableLayout(表格布局)。
   
    一、FrameLayout
   
    这个布局可以看成是墙脚堆东西,有一个四方的矩形的左上角墙脚,我们放了第一个东西,要再放一个,那就在放在原来放的位置的上面,这样依次的放,会盖住原来的东西。这个布局比较简单,也只能放一点比较简单的东西。
   
    二、LinearLayout
   
    线性布局,这个东西,从外框上可以理解为一个div,他首先是一个一个从上往下罗列在屏幕上。每一个LinearLayout里面又可分为垂直布局 (android:orientation="vertical")和水平布局(android:orientation="horizontal" )。当垂直布局时,每一行就只有一个元素,多个元素依次垂直往下;水平布局时,只有一行,每一个元素依次向右排列。
   
    linearLayout中有一个重要的属性 android:layout_weight="1",这个weight在垂直布局时,代表行距;水平的时候代表列宽;weight值越大就越大。
   
    三、AbsoluteLayout
   
    绝对布局犹如div指定了absolute属性,用X,Y坐标来指定元素的位置android:layout_x="20px" android:layout_y="12px" 这种布局方式也比较简单,但是在垂直随便切换时,往往会出问题,而且多个元素的时候,计算比较麻烦。
   
    四、RelativeLayout
   
    相对布局可以理解为某一个元素为参照物,来定位的布局方式。主要属性有:
   
    相对于某一个元素
   
    android:layout_below="@id/aaa" 该元素在 id为aaa的下面
   
    android:layout_toLeftOf="@id/bbb" 改元素的左边是bbb
   
    相对于父元素的地方
   
    android:layout_alignParentLeft="true"  在父元素左对齐
   
    android:layout_alignParentRight="true" 在父元素右对齐
   
    还可以指定边距等,具体详见API
   
    五。TableLayout
   
    表格布局类似Html里面的Table。每一个TableLayout里面有表格行TableRow,TableRow里面可以具体定义每一个元素,设定他的对齐方式 android:gravity="" 。
   
    每一个布局都有自己适合的方式,另外,这五个布局元素可以相互嵌套应用,做出美观的界面。6. 请介绍下Android的数据存储方式

Android提供了5种方式存储数据:
--使用SharedPreferences存储数据;
--文件存储数据;
--SQLite数据库存储数据;
--使用ContentProvider存储数据;
--网络存储数据;

先 说下,Preference,File,DataBase这三种方式分别对应的目录是/data/data/Package Name/Shared_Pref,/data/data/Package Name/files, /data/data/Package Name/database。

在Android中通常使用File存储方式是用Context.openFileOutput(StringfileName, int mode)和Context.openFileInput(String fileName)。
Context.openFileOutput(String fileName, intmode)生成的文件自动存储在/data/data/PackageName/files目录下,其全路径是/data/data/Package Name/files/fileName。注意下,这里的参数fileName不可以包含路径分割符(如"/")。
通常来说,这种方式生成的文件只能在这个apk内访问。但这个结论是指使用Context.openFileInput(StringfileName)的方式。使用这种方式,每个apk只可以访问自己的/data/data/PackageName/files目录下的文件,原因很简单,参数fileName中不可以包含路径分割符,Android会自动在/data/data/PackageName/files目录下寻找文件名为fileName的文件。

一:使用SharedPreferences存储数据

首先说明SharedPreferences存储方式,它是Android提供的用来存储一些简单配置信息的一种机制,例如:登录用户的用户名与密码。其采用了Map数据结构来存储数据,以键值的方式存储,可以简单的读取与写入,具体实例如下:
void ReadSharedPreferences(){
String strName,strPassword;
SharedPreferences  user = getSharedPreferences(“user_info”,0);
strName = user.getString(“NAME”,””);
strPassword = user getString(“PASSWORD”,””);
}
void WriteSharedPreferences(String strName,StringstrPassword){
SharedPreferences  user = getSharedPreferences(“user_info”,0);
uer.edit();
user.putString(“NAME”, strName);
user.putString(“PASSWORD” ,strPassword);
user.commit();
}
数据读取与写入的方法都非常简单,只是在写入的时候有些区别:先调用edit()使其处于编辑状态,然后才能修改数据,最后使用commit()提交修改的数据。实际上SharedPreferences是采用了XML格式将数据存储到设备中,在DDMS中的FileExplorer中的/data/data/<packagename>/shares_prefs下。以上面的数据存储结果为例,打开后可以看到一个user_info.xml的文件,打开后可以看到:
<?xml version=”1.0″encoding=”UTF-8″?>
<map>
<stringname=”NAME”>moandroid</string>
<string name=”PASSWORD”>SharedPreferences</string>
</map>
使用SharedPreferences是有些限制的:只能在同一个包内使用,不能在不同的包之间使用。

二:文件存储数据

 


文件存储方式是一种较常用的方法,在Android中读取/写入文件的方法,与Java中实现I/O的程序是完全一样的,提供了openFileInput()和openFileOutput()方法来读取设备上的文件。FilterInputStream, FilterOutputStream等可以到Java iopackage说明中去详细学习,不再此详细说明,具体实例如下:
String fn = “moandroid.log”;
FileInputStream fis = openFileInput(fn);
FileOutputStream fos =openFileOutput(fn,Context.MODE_PRIVATE);
除此之外,Android还提供了其他函数来操作文件,详细说明请阅读Android SDK。


三:网络存储数据


网络存储方式,需要与Android网络数据包打交道,关于Android 网络数据包的详细说明,请阅读Android SDK引用了JavaSDK的哪些package?。

四:ContentProvider

1、ContentProvider简介


当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据。虽然使用其他方法也可以对外共享数据,但数据访问方式会因数据存储的方式而不同,如:采用文件方式对外共享数据,需要进行文件操作读写数据;采用sharedpreferences共享数据,需要使用sharedpreferencesAPI读写数据。而使用ContentProvider共享数据的好处是统一了数据访问方式。?

2、Uri类简介


Uri代表了要操作的数据,Uri主要包含了两部分信息:1.需要操作的ContentProvider,2.对ContentProvider中的什么数据进行操作,一个Uri由以下几部分组成:
1.scheme:ContentProvider(内容提供者)的scheme已经由Android所规定为:content://。


2.主机名(或Authority):用于唯一标识这个ContentProvider,外部调用者可以根据这个标识来找到它。


3.路径(path):可以用来表示我们要操作的数据,路径的构建应根据业务而定,如下:
? 要操作contact表中id为10的记录,可以构建这样的路径:/contact/10
? 要操作contact表中id为10的记录的name字段, contact/10/name
? 要操作contact表中的所有记录,可以构建这样的路径:/contact?
要操作的数据不一定来自数据库,也可以是文件等他存储方式,如下:
要操作xml文件中contact节点下的name节点,可以构建这样的路径:/contact/name
如果要把一个字符串转换成Uri,可以使用Uri类中的parse()方法,如下:
Uri uri =Uri.parse("content://com.changcheng.provider.contactprovider/contact")
3、UriMatcher、ContentUrist和ContentResolver简介

因为Uri代表了要操作的数据,所以我们很经常需要解析Uri,并从Uri中获取数据。Android系统提供了两个用于操作Uri的工具类,分别为UriMatcher和ContentUris 。掌握它们的使用,会便于我们的开发工作。
? UriMatcher:用于匹配Uri,它的用法如下:


1.首先把你需要匹配Uri路径全部给注册上,如下:
//常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码(-1)。
UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
//如果match()方法匹配content://com.changcheng.sqlite.provider.contactprovider/contact路径,返回匹配码为1
uriMatcher.addURI(“com.changcheng.sqlite.provider.contactprovider”,“contact”, 1);//添加需要匹配uri,如果匹配就会返回匹配码
//如果match()方法匹配content://com.changcheng.sqlite.provider.contactprovider/contact/230路径,返回匹配码为2
uriMatcher.addURI(“com.changcheng.sqlite.provider.contactprovider”,“contact/#”, 2);//#号为通配符

2.注册完需要匹配的Uri后,就可以使用uriMatcher.match(uri)方法对输入的Uri进行匹配,如果匹配就返回匹配码,匹配码是调用addURI()方法传入的第三个参数,假设匹配content://com.changcheng.sqlite.provider.contactprovider/contact路径,返回的匹配码为1。
?
ContentUris:用于获取Uri路径后面的ID部分,它有两个比较实用的方法:
? withAppendedId(uri, id)用于为路径加上ID部分
? parseId(uri)方法用于从路径中获取ID部分
? ContentResolver:当外部应用需要对ContentProvider中的数据进行添加、删除、修改和查询操作时,可以使用ContentResolver 类来完成,要获取ContentResolver对象,可以使用Activity提供的getContentResolver()方法。ContentResolver使用insert、delete、update、query方法,来操作数据。

五:总结说明


以上5中存储方式,在以后的开发过程中,根据设计目标、性能需求、空间需求等找到合适的数据存储方式。Android中的数据存储都是私有的,其他应用程序都是无法访问的,除非通过ContentResolver获取其他程序共享的数据。采用文件方式对外共享数据,需要进行文件操作读写数据;采用sharedpreferences共享数据,需要使用sharedpreferencesAPI读写数据。而使用ContentProvider共享数据的好处是统一了数据访问方式。

8.如何启用Service,如何停用Service

Android中的服务和windows中的服务是类似的东西,服务一般没有用户操作界面,它运行于系统中不容易被用户发觉,可以使用它开发如监控之类的程序。服务的开发比较简单,如下:

第一步:继承Service

public class SMSService extendsService {

}

第二步:在AndroidManifest.xml文件中的<application>节点里对服务进行配置:

<serviceandroid:name=".SMSService"/>


服务不能自己运行,需要通过调用Context.startService()Context.bindService()方法启动服务。这两个方法都可以启动Service,但是它们的使用场合有所不同。使用startService()方法启用服务,调用者与服务之间没有关连,即使调用者退出了,服务仍然运行。使用bindService()方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止,大有“不求同时生,必须同时死”的特点。


如果打算采用Context.startService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onStart()方法。如果调用startService()方法前服务已经被创建,多次调用startService()方法并不会导致多次创建服务,但会导致多次调用onStart()方法。采用startService()方法启动的服务,只能调用Context.stopService()方法结束服务,服务结束时会调用onDestroy()方法。

 

如果打算采用Context.bindService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onBind()方法。这个时候调用者和服务绑定在一起,调用者退出了,系统就会先调用服务的onUnbind()方法,接着调用onDestroy()方法。如果调用bindService()方法前服务已经被绑定,多次调用bindService()方法并不会导致多次创建服务及绑定(也就是说onCreate()onBind()方法并不会被多次调用)。如果调用者希望与正在绑定的服务解除绑定,可以调用unbindService()方法,调用该方法也会导致系统调用服务的onUnbind()-->onDestroy()方法。

服务常用生命周期回调方法如下:

onCreate()该方法在服务被创建时调用,该方法只会被调用一次,无论调用多少次startService()bindService()方法,服务也只被创建一次。

onDestroy()该方法在服务被终止时调用。

 

与采用Context.startService()方法启动服务有关的生命周期方法

onStart()只有采用Context.startService()方法启动服务时才会回调该方法。该方法在服务开始运行时被调用。多次调用startService()方法尽管不会多次创建服务,但onStart() 方法会被多次调用。

 

与采用Context.bindService()方法启动服务有关的生命周期方法

onBind()只有采用Context.bindService()方法启动服务时才会回调该方法。该方法在调用者与服务绑定时被调用,当调用者与服务已经绑定,多次调用Context.bindService()方法并不会导致该方法被多次调用。

onUnbind()只有采用Context.bindService()方法启动服务时才会回调该方法。该方法在调用者与服务解除绑定时被调用

 

采用Context.startService()方法启动服务的代码如下:

public class HelloActivity extends Activity{

   @Override

   public void onCreate(Bundle savedInstanceState){

       ......

       Button button =(Button)this.findViewById(R.id.button);

       button.setOnClickListener(newView.OnClickListener(){

      public void onClick(View v) {

             Intent intent = new Intent(HelloActivity.this,SMSService.class);

             startService(intent);

      }});       

   }

}

 

采用Context.bindService()方法启动服务的代码如下:

public class HelloActivity extends Activity{

    ServiceConnection conn = new ServiceConnection(){

            public void onServiceConnected(ComponentName name, IBinder service){

         }

         public void onServiceDisconnected(ComponentName name){

         }

    };

   @Override public void onCreate(Bundle savedInstanceState){ 

       Button button =(Button)this.findViewById(R.id.button);

       button.setOnClickListener(newView.OnClickListener(){

             public void onClick(View v) {

                Intent intent = new Intent(HelloActivity.this,SMSService.class);

                bindService(intent, conn,Context.BIND_AUTO_CREATE);

                //unbindService(conn);//解除绑定

        }});       

   }

}


之前一定要看看面试题。
 
1. 请描述下Activity的生命周期。 
2. 如果后台的Activity由于某原因被系统回收了,如何在被系统回收之前保存当前状态? 
3. 如何将一个Activity设置成窗口的样式。(Edited by Sodino) 
4. 如何退出Activity?如何安全退出已调用多个Activity的Application? 
5. 请介绍下Android中常用的五种布局。 
6. 请介绍下Android的数据存储方式。(Edited by Sodino) 
7. 请介绍下ContentProvider是如何实现数据共享的。(Edited by Sodino) 
8. 如何启用Service,如何停用Service。(Edited by Sodino) 
9. 注册广播有几种方式,这些方式有何优缺点?请谈谈Android引入广播机制的用意。 
10. 请解释下在单线程模型中Message、Handler、Message Queue、Looper之间的关系。 
11. AIDL的全称是什么?如何工作?能处理哪些类型的数据? 
12. 请解释下Android程序运行时权限与文件系统权限的区别。(Edited by Sodino) 
13. 系统上安装了多种浏览器,能否指定某浏览器访问指定页面?请说明原由。 
14. 有一个一维整型数组int[]data保存的是一张宽为width,高为height的图片像素值信息。请写一个算法,将该图片所有的白色不透明(0xffffffff)像素点的透明度调整为50%。 
15. 你如何评价Android系统?优缺点。


1.请描述下Activity的生命周期
http://weizhulin.blog.51cto.com/1556324/311495
详细介绍一下这几个方法中系统在做什么以及我们应该做什么:

  onCreate:  在这里创建界面,做一些数据的初始化工作

  onStart:   到这一步变成用户可见不可交互 的

  onResume:  变成和用户可交互 的,(在activity栈系统通过栈的方式管理这些个      
                     Activity的最上面,运行完弹出栈,则回到上一个Activity)

  onPause:    到这一步是可见但不可交互 的,系统会停止动画 等消耗CPU 的事情
                   从上文的描述已经知道,应该在这里保存你的一些数据,因为这个时候
                   你的程序的优先级降低,有可能被系统收回。在这里保存的数据,应该在

                   onResume里读出来,注意:这个方法里做的事情时间要短,因为下一
                   个activity不会等到这个方法完成才启动

  onstop:    变得不可见 ,被下一个activity覆盖了

   onDestroy:这是activity被干掉前最后一个被调用方法了,可能是外面类调用finish方
                    法或者是系统为了节省空间将它暂时性的干掉,可以用isFinishing()来判
                    断它,如果你有一个Progress Dialog在线程中转动,请在onDestroy里
                    把他cancel掉,不然等线程结束的时候,调用Dialog的cancel方法会抛
                    异常的。

             
onPause,onstop, onDestroy,三种状态 下 activity都有可能被系统干掉
为了保证程序的正确性,你要在onPause()里写上持久层操作的代码,将用户编辑的内容都保存到存储介质上(一般都是数据库)。实际工作中因为生命周期的变化而带来的问题也很多,比如你的应用程序起了新的线程在跑,这时候中断了,你还要去维护那个线程,是暂停还是杀掉还是数据回滚,是吧?因为Activity可能被杀掉,所以线程中使用的变量和一些界面元素就千万要注意了,一般我都是采用Android的消息机制[Handler,Message]来处理多线程和界面交互的问题。这个我后面会讲一些,最近因为这些东西头已经很大了,等我理清思绪再跟大家分享。

 2. 如果后台的Activity由于某原因被系统回收了,如何在被系统回收之前保存当前状态?
当你的程序中某一个Activity A 在运行时中,主动或被动地运行另一个新的Activity B 这个时候A会执行

Java代码


 

  1. public 
  2. void onSaveInstanceState(Bundle outState)    
  3.     super.onSaveInstanceState(outState);    
  4.     outState.putLong("id", 1234567890);    
  5.    
  6.  
  7. public void onSaveInstanceState(Bundle outState)    super.onSaveInstanceState(outState);    outState.putLong("id", 1234567890);} 
  8.  


B 完成以后又会来找A, 这个时候就有两种情况,一种是A被回收,一种是没有被回收,被回
收的A就要重新调用onCreate()方法,不同于直接启动的是这回onCreate()里是带上参数
savedInstanceState,没被收回的就还是onResume就好了。

savedInstanceState是一个Bundle对象,你基本上可以把他理解为系统帮你维护的一个Map对象。在onCreate()里你可能会用到它,如果正常启动onCreate就不会有它,所以用的时候要判断一下是否为空。

Java代码


if(savedInstanceState !=null){  
    long id =savedInstanceState.getLong("id");  
 

if(savedInstanceState !=null){    long id = savedInstanceState.getLong("id");}


就像官方的Notepad教程里的情况,你正在编辑某一个note,突然被中断,那么就把这个note的id记住,再起来的时候就可以根据这个id去把那个note取出来,程序就完整一些。这也是看你的应用需不需要保存什么,比如你的界面就是读取一个列表,那就不需要特殊记住什么,哦,没准你需要记住滚动条的位置...

3. 如何将一个Activity设置成窗口的样式 
简单你只需要设置 一下Activity的主题就可以了在AndroidManifest.xml 中定义 Activity的
地方一句话:


Xml代码


 

  1. android :theme="@android:style/Theme.Dialog"  
  2.  
  3. android:theme="@android:style/Theme.Dialog"  
  4.  


这就使你的应用程序变成对话框的形式弹出来了,或者


Xml代码


 

  1. android:theme="@android:style/Theme.Translucent"  
  2.  
  3. android:theme="@android:style/Theme.Translucent"  
  4.  

就变成半透明的,[友情提示-.-]类似的这种activity的属性可以在android.R.styleable类的AndroidManifestActivity方法中看到,AndroidManifest.xml中所有元素的属性的介绍都可以参考这个类android.R.styleable

上面说的是属性名称,具体有什么值是在android.R.style中可以看到,比如这个"@android:style/Theme.Dialog"就对应于android.R.style.Theme_Dialog ,('_'换成'.'<--注意:这个是文章内容不是笑脸)就可以用在描述文件中了,找找类定义和描述文件中的对应关系就都明白了。


4. 如何退出Activity
对于单一Activity的应用来说,退出很简单,直接finish()即可。
当然,也可以用killProcess()和System.exit()这样的方法。现提供几个方法,供参考:

1、抛异常强制退出:
该方法通过抛异常,使程序Force Close。
验证可以,但是,需要解决的问题是,如何使程序结束掉,而不弹出Force Close的窗口。

2、记录打开的Activity:
每打开一个Activity,就记录下来。在需要退出时,关闭每一个Activity即可。

3、发送特定广播:
在需要结束应用时,发送一个特定的广播,每个Activity收到广播后,关闭即可。

4、递归退出
在打开新的Activity时使用startActivityForResult,然后自己加标志,在onActivityResult中处理,递归关闭。

除了第一个,都是想办法把每一个Activity都结束掉,间接达到目的。
但是这样做同样不完美。
你会发现,如果自己的应用程序对每一个Activity都设置了nosensor,在两个Activity结束的间隙,sensor可能有效了。
但至少,我们的目的达到了,而且没有影响用户使用。

为了编程方便,最好定义一个Activity基类,处理这些共通问题。5.请介绍下Android中常用的五种布局 Android布局是应用界面开发的重要一环,在Android中,共有五种布局方式,分别是:FrameLayout(框架布 局),LinearLayout (线性布局),AbsoluteLayout(绝对布局),RelativeLayout(相对布局),TableLayout(表格布局)。
   
    一、FrameLayout
   
    这个布局可以看成是墙脚堆东西,有一个四方的矩形的左上角墙脚,我们放了第一个东西,要再放一个,那就在放在原来放的位置的上面,这样依次的放,会盖住原来的东西。这个布局比较简单,也只能放一点比较简单的东西。
   
    二、LinearLayout
   
    线性布局,这个东西,从外框上可以理解为一个div,他首先是一个一个从上往下罗列在屏幕上。每一个LinearLayout里面又可分为垂直布局 (android:orientation="vertical")和水平布局(android:orientation="horizontal" )。当垂直布局时,每一行就只有一个元素,多个元素依次垂直往下;水平布局时,只有一行,每一个元素依次向右排列。
   
    linearLayout中有一个重要的属性 android:layout_weight="1",这个weight在垂直布局时,代表行距;水平的时候代表列宽;weight值越大就越大。
   
    三、AbsoluteLayout
   
    绝对布局犹如div指定了absolute属性,用X,Y坐标来指定元素的位置android:layout_x="20px" android:layout_y="12px" 这种布局方式也比较简单,但是在垂直随便切换时,往往会出问题,而且多个元素的时候,计算比较麻烦。
   
    四、RelativeLayout
   
    相对布局可以理解为某一个元素为参照物,来定位的布局方式。主要属性有:
   
    相对于某一个元素
   
    android:layout_below="@id/aaa" 该元素在 id为aaa的下面
   
    android:layout_toLeftOf="@id/bbb" 改元素的左边是bbb
   
    相对于父元素的地方
   
    android:layout_alignParentLeft="true"  在父元素左对齐
   
    android:layout_alignParentRight="true" 在父元素右对齐
   
    还可以指定边距等,具体详见API
   
    五。TableLayout
   
    表格布局类似Html里面的Table。每一个TableLayout里面有表格行TableRow,TableRow里面可以具体定义每一个元素,设定他的对齐方式 android:gravity="" 。
   
    每一个布局都有自己适合的方式,另外,这五个布局元素可以相互嵌套应用,做出美观的界面。6. 请介绍下Android的数据存储方式

Android提供了5种方式存储数据:
--使用SharedPreferences存储数据;
--文件存储数据;
--SQLite数据库存储数据;
--使用ContentProvider存储数据;
--网络存储数据;

先 说下,Preference,File,DataBase这三种方式分别对应的目录是/data/data/Package Name/Shared_Pref,/data/data/Package Name/files, /data/data/Package Name/database。

在Android中通常使用File存储方式是用Context.openFileOutput(StringfileName, int mode)和Context.openFileInput(String fileName)。
Context.openFileOutput(String fileName, intmode)生成的文件自动存储在/data/data/PackageName/files目录下,其全路径是/data/data/Package Name/files/fileName。注意下,这里的参数fileName不可以包含路径分割符(如"/")。
通常来说,这种方式生成的文件只能在这个apk内访问。但这个结论是指使用Context.openFileInput(StringfileName)的方式。使用这种方式,每个apk只可以访问自己的/data/data/PackageName/files目录下的文件,原因很简单,参数fileName中不可以包含路径分割符,Android会自动在/data/data/PackageName/files目录下寻找文件名为fileName的文件。

一:使用SharedPreferences存储数据

首先说明SharedPreferences存储方式,它是Android提供的用来存储一些简单配置信息的一种机制,例如:登录用户的用户名与密码。其采用了Map数据结构来存储数据,以键值的方式存储,可以简单的读取与写入,具体实例如下:
void ReadSharedPreferences(){
String strName,strPassword;
SharedPreferences  user = getSharedPreferences(“user_info”,0);
strName = user.getString(“NAME”,””);
strPassword = user getString(“PASSWORD”,””);
}
void WriteSharedPreferences(String strName,StringstrPassword){
SharedPreferences  user = getSharedPreferences(“user_info”,0);
uer.edit();
user.putString(“NAME”, strName);
user.putString(“PASSWORD” ,strPassword);
user.commit();
}
数据读取与写入的方法都非常简单,只是在写入的时候有些区别:先调用edit()使其处于编辑状态,然后才能修改数据,最后使用commit()提交修改的数据。实际上SharedPreferences是采用了XML格式将数据存储到设备中,在DDMS中的FileExplorer中的/data/data/<packagename>/shares_prefs下。以上面的数据存储结果为例,打开后可以看到一个user_info.xml的文件,打开后可以看到:
<?xml version=”1.0″encoding=”UTF-8″?>
<map>
<stringname=”NAME”>moandroid</string>
<string name=”PASSWORD”>SharedPreferences</string>
</map>
使用SharedPreferences是有些限制的:只能在同一个包内使用,不能在不同的包之间使用。

二:文件存储数据

 


文件存储方式是一种较常用的方法,在Android中读取/写入文件的方法,与Java中实现I/O的程序是完全一样的,提供了openFileInput()和openFileOutput()方法来读取设备上的文件。FilterInputStream, FilterOutputStream等可以到Java iopackage说明中去详细学习,不再此详细说明,具体实例如下:
String fn = “moandroid.log”;
FileInputStream fis = openFileInput(fn);
FileOutputStream fos =openFileOutput(fn,Context.MODE_PRIVATE);
除此之外,Android还提供了其他函数来操作文件,详细说明请阅读Android SDK。


三:网络存储数据


网络存储方式,需要与Android网络数据包打交道,关于Android 网络数据包的详细说明,请阅读Android SDK引用了JavaSDK的哪些package?。

四:ContentProvider

1、ContentProvider简介


当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据。虽然使用其他方法也可以对外共享数据,但数据访问方式会因数据存储的方式而不同,如:采用文件方式对外共享数据,需要进行文件操作读写数据;采用sharedpreferences共享数据,需要使用sharedpreferencesAPI读写数据。而使用ContentProvider共享数据的好处是统一了数据访问方式。?

2、Uri类简介


Uri代表了要操作的数据,Uri主要包含了两部分信息:1.需要操作的ContentProvider,2.对ContentProvider中的什么数据进行操作,一个Uri由以下几部分组成:
1.scheme:ContentProvider(内容提供者)的scheme已经由Android所规定为:content://。


2.主机名(或Authority):用于唯一标识这个ContentProvider,外部调用者可以根据这个标识来找到它。


3.路径(path):可以用来表示我们要操作的数据,路径的构建应根据业务而定,如下:
? 要操作contact表中id为10的记录,可以构建这样的路径:/contact/10
? 要操作contact表中id为10的记录的name字段, contact/10/name
? 要操作contact表中的所有记录,可以构建这样的路径:/contact?
要操作的数据不一定来自数据库,也可以是文件等他存储方式,如下:
要操作xml文件中contact节点下的name节点,可以构建这样的路径:/contact/name
如果要把一个字符串转换成Uri,可以使用Uri类中的parse()方法,如下:
Uri uri =Uri.parse("content://com.changcheng.provider.contactprovider/contact")
3、UriMatcher、ContentUrist和ContentResolver简介

因为Uri代表了要操作的数据,所以我们很经常需要解析Uri,并从Uri中获取数据。Android系统提供了两个用于操作Uri的工具类,分别为UriMatcher和ContentUris 。掌握它们的使用,会便于我们的开发工作。
? UriMatcher:用于匹配Uri,它的用法如下:


1.首先把你需要匹配Uri路径全部给注册上,如下:
//常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码(-1)。
UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
//如果match()方法匹配content://com.changcheng.sqlite.provider.contactprovider/contact路径,返回匹配码为1
uriMatcher.addURI(“com.changcheng.sqlite.provider.contactprovider”,“contact”, 1);//添加需要匹配uri,如果匹配就会返回匹配码
//如果match()方法匹配content://com.changcheng.sqlite.provider.contactprovider/contact/230路径,返回匹配码为2
uriMatcher.addURI(“com.changcheng.sqlite.provider.contactprovider”,“contact/#”, 2);//#号为通配符

2.注册完需要匹配的Uri后,就可以使用uriMatcher.match(uri)方法对输入的Uri进行匹配,如果匹配就返回匹配码,匹配码是调用addURI()方法传入的第三个参数,假设匹配content://com.changcheng.sqlite.provider.contactprovider/contact路径,返回的匹配码为1。
?
ContentUris:用于获取Uri路径后面的ID部分,它有两个比较实用的方法:
? withAppendedId(uri, id)用于为路径加上ID部分
? parseId(uri)方法用于从路径中获取ID部分
? ContentResolver:当外部应用需要对ContentProvider中的数据进行添加、删除、修改和查询操作时,可以使用ContentResolver 类来完成,要获取ContentResolver对象,可以使用Activity提供的getContentResolver()方法。ContentResolver使用insert、delete、update、query方法,来操作数据。

五:总结说明


以上5中存储方式,在以后的开发过程中,根据设计目标、性能需求、空间需求等找到合适的数据存储方式。Android中的数据存储都是私有的,其他应用程序都是无法访问的,除非通过ContentResolver获取其他程序共享的数据。采用文件方式对外共享数据,需要进行文件操作读写数据;采用sharedpreferences共享数据,需要使用sharedpreferencesAPI读写数据。而使用ContentProvider共享数据的好处是统一了数据访问方式。

8.如何启用Service,如何停用Service

Android中的服务和windows中的服务是类似的东西,服务一般没有用户操作界面,它运行于系统中不容易被用户发觉,可以使用它开发如监控之类的程序。服务的开发比较简单,如下:

第一步:继承Service

public class SMSService extendsService {

}

第二步:在AndroidManifest.xml文件中的<application>节点里对服务进行配置:

<serviceandroid:name=".SMSService"/>


服务不能自己运行,需要通过调用Context.startService()Context.bindService()方法启动服务。这两个方法都可以启动Service,但是它们的使用场合有所不同。使用startService()方法启用服务,调用者与服务之间没有关连,即使调用者退出了,服务仍然运行。使用bindService()方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止,大有“不求同时生,必须同时死”的特点。


如果打算采用Context.startService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onStart()方法。如果调用startService()方法前服务已经被创建,多次调用startService()方法并不会导致多次创建服务,但会导致多次调用onStart()方法。采用startService()方法启动的服务,只能调用Context.stopService()方法结束服务,服务结束时会调用onDestroy()方法。

 

如果打算采用Context.bindService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onBind()方法。这个时候调用者和服务绑定在一起,调用者退出了,系统就会先调用服务的onUnbind()方法,接着调用onDestroy()方法。如果调用bindService()方法前服务已经被绑定,多次调用bindService()方法并不会导致多次创建服务及绑定(也就是说onCreate()onBind()方法并不会被多次调用)。如果调用者希望与正在绑定的服务解除绑定,可以调用unbindService()方法,调用该方法也会导致系统调用服务的onUnbind()-->onDestroy()方法。

服务常用生命周期回调方法如下:

onCreate()该方法在服务被创建时调用,该方法只会被调用一次,无论调用多少次startService()bindService()方法,服务也只被创建一次。

onDestroy()该方法在服务被终止时调用。

 

与采用Context.startService()方法启动服务有关的生命周期方法

onStart()只有采用Context.startService()方法启动服务时才会回调该方法。该方法在服务开始运行时被调用。多次调用startService()方法尽管不会多次创建服务,但onStart() 方法会被多次调用。

 

与采用Context.bindService()方法启动服务有关的生命周期方法

onBind()只有采用Context.bindService()方法启动服务时才会回调该方法。该方法在调用者与服务绑定时被调用,当调用者与服务已经绑定,多次调用Context.bindService()方法并不会导致该方法被多次调用。

onUnbind()只有采用Context.bindService()方法启动服务时才会回调该方法。该方法在调用者与服务解除绑定时被调用

 

采用Context.startService()方法启动服务的代码如下:

public class HelloActivity extends Activity{

   @Override

   public void onCreate(Bundle savedInstanceState){

       ......

       Button button =(Button)this.findViewById(R.id.button);

       button.setOnClickListener(newView.OnClickListener(){

      public void onClick(View v) {

             Intent intent = new Intent(HelloActivity.this,SMSService.class);

             startService(intent);

      }});       

   }

}

 

采用Context.bindService()方法启动服务的代码如下:

public class HelloActivity extends Activity{

    ServiceConnection conn = new ServiceConnection(){

            public void onServiceConnected(ComponentName name, IBinder service){

         }

         public void onServiceDisconnected(ComponentName name){

         }

    };

   @Override public void onCreate(Bundle savedInstanceState){ 

       Button button =(Button)this.findViewById(R.id.button);

       button.setOnClickListener(newView.OnClickListener(){

             public void onClick(View v) {

                Intent intent = new Intent(HelloActivity.this,SMSService.class);

                bindService(intent, conn,Context.BIND_AUTO_CREATE);

                //unbindService(conn);//解除绑定

        }});       

   }

}


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/294516.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C# WPF MVVM开发框架Caliburn.Micro Screens, Conductors 和 Composition⑦

01—Screens, Conductors and CompositionActions, Coroutines and Conventions往往最能吸引Caliburn.Micro的注意力&#xff0c;但如果你想让你的UI设计得更好&#xff0c;那么了解屏幕和导体可能是最重要的。如果您想利用合成&#xff0c;这一点尤其重要。杰里米米勒最近在为…

【原创】mysql数据库异常:data truncate for column “*” at row *;data too long *。原因,及解决。...

数据库异常 1.data truncate for column “*” at row *&#xff1a; 就是数据被截断&#xff0c;类似时间被截短&#xff08;字段属性为date&#xff0c;要存储的数据为timestamp&#xff09;&#xff0c;精度下降。 将数据库的字段属性调整合适&#xff0c;或者将要存储的数据…

正则表达式匹配汉字

纯汉字&#xff1a;^[\u4E00-\u9FA5]$ 2E80&#xff5e;33FFh&#xff1a;中日韩符号区。收容康熙字典部首、中日韩辅助部首、注音符号、日本假名、韩文音符&#xff0c;中日韩的符号、标点、带圈或带括符文数字、月份&#xff0c;以及日本的假名组合、单位、年号、月份、日期、…

如此生猛的纪录片,背后是难以置信的故事!

全世界只有3.14 % 的人关注了爆炸吧知识美国纪录片大师阿尔伯特梅索斯所言&#xff1a;“制作一部电影不是为一个问题寻求答案&#xff0c;而是尝试去捕捉生活本身。”从赵忠祥那句大名鼎鼎的“春天到了&#xff0c;又到了动物交配的季节”开始&#xff0c;纪录片看似没有像影视…

java 字符串 日期格式化_java字符串转换为时间类型以及时间的格式化实例

java字符串转换为时间类型以及时间的格式化实例。时间的应用几乎是每个项目都要接触到的&#xff0c;也是每个java程序员所熟知的&#xff0c;但是不记得怎么使用也是无所谓的&#xff0c;我们可以查一下java api文档嘛&#xff01;或者直接百度一下就可以了。下面就是时间类型…

[转]Excel导入异常Cannot get a text value from a numeric cell解决

原文地址:http://blog.csdn.net/ysughw/article/details/9288307 POI操作Excel时偶尔会出现Cannot get a text value from a numeric cell的异常错误。 异常原因&#xff1a;Excel数据Cell有不同的类型&#xff0c;当我们试图从一个数字类型的Cell读取出一个字符串并写入数据库…

Android之面试题总结加强版(一)

转载&#xff1a;http://blog.csdn.net/itachi85/article/details/7426451 自己总结的最强android应用面试题集 1.activity的生命周期。 方法 描述 可被杀死 下一个 onCreate() 在activity第一次被创建的时候调用。这里是你做所有初始化设置的地方──创建视图、绑定…

官宣!.NET官网发布中⽂版

#官宣.NET简体中文版.NET的官网终于正式发布简体中⽂版本了&#xff0c;⽽且是作为官方支持的第一梯队&#xff01;这是一个影响未来中国.NET技术生态的大事。我承认好的英文是从事IT技术的重要基础&#xff0c;但本地化语言能帮助更多人了解、学习、应用该技术。.NET官网中文版…

微信需要内容吗?

11月30日&#xff0c;腾讯对微信公众平台的群发系统进行了全面升级&#xff0c;升级后的平台关闭了单条图文和多条图文编辑&#xff0c;并求取消了帐号互推、分享到朋友圈按钮等功能。导致本次更新的原因是因为美丽说、蘑菇街等大号以及一些投机分子利用微信可以从第三方应用向…

爱因斯坦为什么不是普通人?看他怎么喝茶就明白了,差距太明显了!没法比.......

全世界只有3.14 % 的人关注了爆炸吧知识来源&#xff1a;Закройте, дует看到上面这个动图&#xff0c;猜到这篇文章要讲什么了吗&#xff1f;讲泡茶&#xff0c;啊呸&#xff01;讲“茶叶悖论”&#xff0c;一个爱因斯坦喝茶时不经意间看到的物理现象&#xff0c;然…

在应用程序中实现对NandFlash的操作

以TC58NVG2S3ETA00 为例&#xff1a; 下面是它的一些物理参数&#xff1a; 图一 图二 图三 图四 图五 图6-0 图6-1 说明一下&#xff0c;在图6-1中中间的那个布局表可以看做是实际的NandFlash一页数据的布局&#xff0c;其中Data区域用于存放有效的数据&#xff0c;也就是我们可…

java的集合应用_Java之集合类应用总结

1.集合类类图Collection├List│├LinkedList│├ArrayList│└Vector│ └Stack└Set├HashSet├TreeSet├LinkedHashSetMap├Hashtable├HashMap├WeakHashMap└SortedMap└TreeMap2.分类介绍Collection是最基本的集合接口&#xff0c;JDK提供的类都继承自Collection的“子接…

Oracle级联查询

在ORACLE 数据库中有一种方法可以实现级联查询select * //要查询的字段from table //具有子接点ID与父接点ID的表 start with selfidid //给定一个startid(字段名为子接点ID&#xff0c;及开始的ID号)connect by prior selfidparentid …

Android面试题总结加强版(二)

http://blog.csdn.net/superjunjin/article/details/7855995 16.Android常用控件的信息 单选框(RadioButton与RadioGroup)&#xff1a; RadioGroup用于对单选框进行分组&#xff0c;相同组内的单选框只有一个单选框被选中。 事件&#xff1a;setOnCheckedChangeListener()&…

1 盒用 1 年,这个防雾黑科技,让你的眼镜再也不起雾!

▲ 点击查看本来被疫情这么一闹&#xff0c;口罩就已经成了我们离不开的刚需品。现在天气大幅度降温&#xff0c;口罩更不能摘了&#xff0c;必须得御寒防疫两手抓&#xff01;虽然口罩的优点有目共睹&#xff0c;但它最大的 Bug 也够大伙儿吐槽一顿了——口罩眼镜一秒起雾&…

福利好礼现金大奖等你来→首届 .NET Conf China Hackathon 火热报名中!

.NET 开源以来越来越多的开发者和企业开始加入到 .NET 的生态。.NET 6 是 .NET Framework, .NET Core 和 Mono 三个平台完成融合的第一个长期支持版本&#xff0c;无论你是开发云原生应用&#xff0c;还是 IOT 应用&#xff0c;移动端&#xff0c;桌面应用&#xff0c;.NET 6 …

ciscodk新科目——1Z1-807

1Z1-807是ciscodk.com刚更新的科目&#xff0c;具体信息如下&#xff1a; 1Z1-807 Java Enterprise Edition 6 Enterprise Architect Certified Master Exam (Step 1 of 3) 想知更多新科目就在ciscodk .com转载于:https://blog.51cto.com/ciscodk/1088893

一站式解决,Android 拍照 图库的各种问题

在android开发中, 在一些编辑个人信息的时候,经常会有头像这么一个东西,就两个方面,调用系统相机拍照,调用系统图库获取图片.但是往往会遇到各种问题: 1.oom 2.图片方向不对 3.activity result 的时候data null 4.调用图库的时候没找到软件 嘿嘿..开代码: 首先是调用系统拍照…

(转载)9个主流的开源许可协议[整理]

http://univasity.iteye.com/blog/1292658 关于开源许可现今存在的开源协议很多&#xff0c;而经过Open Source Initiative 组织通过批准的开源协议目前有60多种&#xff08;http://www.opensource.org/licenses/alphabetical &#xff09;。我们在常见的开源协议如BSD, GPL, L…

java属于面相_[Java教程]面相对象

[Java教程]面相对象0 2018-09-13 16:00:26面向对象那什么是面向对象&#xff1f; 在Java 中&#xff0c;我们是一切皆对象&#xff0c;所有的方法都是围绕着对象来的。面相对象是相对面向过程而来的&#xff0c;他们都是一种思想&#xff0c;面向过程&#xff0c;强调的是一种功…