您的位置:首页 > 职场人生

Android开发-基本概念小整理(一)为了面试的小伙伴们所准备~~

2016-12-06 16:22 676 查看
转载请注明出处:http://blog.csdn.net/iwanghang/

我正在参加CSDN 2016博客之星评选,希望得到您的宝贵一票~
http://blog.csdn.net/vote/candidate.html?username=iwanghang
请为我投票,谢谢 ~~
如果没有CSDN账号 直接使用微信/QQ/微博登陆 就能投票了~~

1.请解释下在单线程模型中Message,Handler,Message Queue,Looper之间的关系。
简单的说,Handler获取当前线程中的looper对象,looper用来从存放Message的MessageQueue中取出Message,再有Handler进行Message的分发和处理。
Message Queue(消息队列):用来存放通过Handler发布的消息,通常附属于某一个创建它的线程,可以通过Looper.myQueue()得到当前线程的消息队列。
Handler:可以发布或者处理一个消息或者操作一个Runnable,通过Handler发布消息,消息将只会发送到与它关联的消息队列,也只能处理该消息队列中的消息。
Looper:是Handler和消息队列之间通讯桥梁,程序组件首先通过Handler把消息传递给Looper,Looper把消息放入队列。Looper也把消息队列里的消息广播给所有的。
Handler:Handler接受到消息后调用handleMessage进行处理。
Message:消息的类型,在Handler类中的handleMessage方法中得到单个的消息进行处理。
在单线程模型下,为了线程通信问题,Android设计了一个Message Queue(消息队列), 线程间可以通过该Message Queue并结合Handler和Looper组件进行信息交换。下面将对它们进行分别介绍:
1. Message 
Message消息,理解为线程间交流的信息,处理数据后台线程需要更新UI,则发送Message内含一些数据给UI线程。
2. Handler 
Handler处理者,是Message的主要处理者,负责Message的发送,Message内容的执行处理。后台线程就是通过传进来的 Handler对象引用来sendMessage(Message)。而使用Handler,需要implement 该类的 handleMessage(Message)方法,它是处理这些Message的操作内容,例如Update UI。通常需要子类化Handler来实现handleMessage方法。
3. Message Queue 
Message Queue消息队列,用来存放通过Handler发布的消息,按照先进先出执行。
每个message queue都会有一个对应的Handler。Handler会向message queue通过两种方法发送消息:sendMessage或post。这两种消息都会插在message queue队尾并按先进先出执行。但通过这两种方法发送的消息执行的方式略有不同:通过sendMessage发送的是一个message对象,会被 Handler的handleMessage()函数处理;而通过post方法发送的是一个runnable对象,则会自己执行。
4. Looper 
Looper是每条线程里的Message Queue的管家。Android没有Global的Message Queue,而Android会自动替主线程(UI线程)建立Message Queue,但在子线程里并没有建立Message Queue。所以调用Looper.getMainLooper()得到的主线程的Looper不为NULL,但调用Looper.myLooper() 得到当前线程的Looper就有可能为NULL。对于子线程使用Looper,API Doc提供了正确的使用方法:这个Message机制的大概流程:
1. 在Looper.loop()方法运行开始后,循环地按照接收顺序取出Message Queue里面的非NULL的Message。
2. 一开始Message Queue里面的Message都是NULL的。当Handler.sendMessage(Message)到Message Queue,该函数里面设置了那个Message对象的target属性是当前的Handler对象。随后Looper取出了那个Message,则调用 该Message的target指向的Hander的dispatchMessage函数对Message进行处理。在dispatchMessage方法里,如何处理Message则由用户指定,三个判断,优先级从高到低:
1) Message里面的Callback,一个实现了Runnable接口的对象,其中run函数做处理工作;
2) Handler里面的mCallback指向的一个实现了Callback接口的对象,由其handleMessage进行处理;
3) 处理消息Handler对象对应的类继承并实现了其中handleMessage函数,通过这个实现的handleMessage函数处理消息。
由此可见,我们实现的handleMessage方法是优先级最低的!
3. Handler处理完该Message (update UI) 后,Looper则设置该Message为NULL,以便回收!
在网上有很多文章讲述主线程和其他子线程如何交互,传送信息,最终谁来执行处理信息之类的,个人理解是最简单的方法——判断Handler对象里面的Looper对象是属于哪条线程的,则由该线程来执行! 
1. 当Handler对象的构造函数的参数为空,则为当前所在线程的Looper; 
2. Looper.getMainLooper()得到的是主线程的Looper对象,Looper.myLooper()得到的是当前线程的Looper对象。

2.如果有个100M大的文件,需要上传至服务器中,而服务器form表单最大只能上传2M,可以用什么方法。
使用Http协议上传数据,特别是在android下,跟form没什么关系。传统的在web中,在form中写文件上传,其实浏览器所做的就是将我们的数据进行解析组拼成字符串,以流的方式发送到服务器,且上传文件用的都是POST方式,POST方式对大小没什么限制。
3、内存溢出和内存泄漏有什么区别?何时会产生内存泄漏?内存优化有哪些方法?
内存溢出通俗理解就是软件(应用)运行需要的内存,超出了它可用的最大内存。
内存泄漏就是我们对某一内存空间的使用,使用完成后没有释放。
内存优化:Android中容易内存溢出的部分,就是图片的加载,我们可以使用图片的压缩加上使用LruCache缓存的目的
来控制图片所能够使用的内存。还有对于比较耗资源的对象及时的关闭,例如Database Conn,各种传感器,Service等等。

4.AsyncTask使用在哪些场景?它的缺陷是什么?如何解决?
AsyncTask 运用的场景就是我们需要进行一些耗时的操作,耗时操作完成后更新主线程,或者在操作过程中对主线程的UI进行更新。
缺陷:AsyncTask中维护着一个长度为128的线程池,同时可以执行5个工作线程,还有一个缓冲队列,当线程池中已有128个线程,缓冲队列已满时,如果此时向线程提交任务,将会抛出RejectedExecutionException。
解决的方法:由一个控制线程来处理AsyncTask的调用判断线程池是否满了,如果满了则线程睡眠否则请求AsyncTask继续处理。

5.assest文件夹里放文件,对于文件的大小有没有限制?
assets目录更像一个附录类型的目录,Android不会为这个目录中的文件生成ID并保存在R类当中,因此它与Android中的一些类和方法兼容度更低。同时,由于你需要一个字符串路径来获取这个目录下的文件描述符,访问的速度会更慢。但是把一些文件放在这个目录下会使一些操作更加方便,比方说拷贝一个数据库文件到系统内存中。要注意的是,你无法在Android XML文件中引用到assets目录下的文件,只能通过AssetManager来访问这些文件。数据库文件和游戏数据等放在这个目录下是比较合适的。这两者中单个文件大小不能超过1M的错误描述也在传播,即如果读取超过1M的文件会报IOException,还引申出种种解决方案。不应该有这样的限制,为了验证这个说法写了个Demo,发现将近5M的压缩包在assets和raw中都能正常访问,在这里纠正一下,理论上只要打包不超过Android APK 50M大小的限制都是没有问题的。当然了,不排除是Android很早期的时候因为设备硬件原因aapt在编译的时候对这两个文件夹大小做出了限制,如果是这样,较新版的ADT应该不会出现这种情况。

6.启动一个程序,可以主界面点击图标进入,也可以从一个程序中跳转过去,二者有什么区别?
是因为启动程序(主界面也是一个app),发现了在这个程序中存在一个设置为<category android:name="android.intent.category.LAUNCHER" />的activity,所以这个launcher会把icon提出来,放在主界面上。当用户点击icon的时候,发出一个Intent:Intent intent = mActivity.getPackageManager().getLaunchIntentForPackage(packageName);
mActivity.startActivity(intent);跳过去可以跳到任意允许的页面,如一个程序可以下载,那么真正下载的页面可能不是首页(也有可能是首页),这时还是构造一个Intent,startActivity。
这个intent中的action可能有多种view,download都有可能。系统会根据第三方程序向系统注册的功能,为你的Intent选择可以打开的程序或者页面。所以唯一的一点不同的是从icon的点击启动的intent的action是相对单一的,从程序中跳转或者启动可能样式更多一些。本质是相同的。

7.程序之间的亲和性的理解。
1、默认情况下一个应用的所有Activity都是具有相同的affinity,都是从application中继承,application的affinity
默认就是manifest的包名。
2、affinity对Activity来说,就像是身份证一样,可以告诉所在的Task,自己属于其中的一员。
3、应用场合:
a:根据affinity重新为Activity选择合适的宿主Task;
b:与allowTaskReparenting属性配合;
c:启动Activity使用Intent设置了FLAG_ACTIVITY_NEW_TASK标记。

8.同一个程序,但不同的Activity是否可以放在不同的Task任务栈中?
可以放在不同的Task中。需要为不同的activity设置不同的affinity属性,启动activity的Intent需要包含FLAG_ACTIVITY_NEW_TASK标记。

9.横竖屏切换时候Activity的生命周期。
1、不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次。
2、设置Activity的android:configChanges="orientation"时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次。
3、设置Activity的android:configChanges="orientation|keyboardHidden"时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法。

10.AIDL的全称是什么?如何工作?
全称是:Android Interface Define Language(Android接口定义语言)
在Android中, 每个应用程序都可以有自己的进程. 在写UI应用的时候, 经常要用到Service. 在不同的进程中, 怎样传递对象呢? 显然, Java中不允许跨进程内存共享。
因此传递对象, 只能把对象拆分成操作系统能理解的简单形式, 以达到跨界对象访问的目的. 在J2EE中,采用RMI的方式, 可以通过序列化传递对象. 在Android中, 则采用AIDL的方式. 理论上AIDL可以传递Bundle,实际上做起来却比较麻烦。
AIDL(AndRoid接口描述语言)是一种借口描述语言; 编译器可以通过aidl文件生成一段代码,通过预先定义的接口达到两个进程内部通信进程的目的. 如果需要在一个Activity中, 访问另一个Service中的某个对象, 需要先将对象转化成AIDL可识别的参数(可能是多个参数), 然后使用AIDL来传递这些参数, 在消息的接收端, 使用这些参数组装成自己需要的对象.AIDL的IPC的机制和COM或CORBA类似, 是基于接口的,但它是轻量级的。它使用代理类在客户端和实现层间传递值. 如果要使用AIDL,需要完成2件事情: 1. 引入AIDL的相关类.; 2. 调用aidl产生的class。
AIDL的创建方法:
AIDL语法很简单,可以用来声明一个带一个或多个方法的接口,也可以传递参数和返回值。 由于远程调用的需要, 这些参数和返回值并不是任何类型。
下面是些AIDL支持的数据类型:
1. 不需要import声明的简单Java编程语言类型(int,boolean等)
2. String, CharSequence不需要特殊声明
3. List, Map和Parcelables类型, 这些类型内所包含的数据成员也只能是简单数据类型, String等其他比支持的类型

11.dvm的进程和Linux的进程, 应用程序的进程是否为同一个概念?
DVM指dalivk的虚拟机。每一个Android应用程序都在它自己的进程中运行,都拥有一个独立的Dalvik虚拟机实例。而每一个DVM都是在Linux 中的一个进程,所以说可以认为是同一个概念。Dalvik是Google公司自己设计用于Android平台的Java虚拟机,每一个Dalvik 应用作为一个独立的Linux 进程执行。独立的进程可以防止在虚拟机崩溃的时候所有程序都被关闭。

12. 什么是Activity?
四大组件之一,一般的,一个用户交互界面对应一个activity, activity 是Context的子类,同时实现了window.callback和keyevent.callback, 可以处理与窗体用户交互的事件. 我开发常用的的有ListActivity,PreferenceActivity 等…如果界面有共同的特点或者功能的时候,还会自己定义一个BaseActivity.

13. 请描述一下Activity生命周期。
    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]来处理多线程和界面交互的问题。
其实这些方法都是两两对应的,onCreate创建与onDestroy销毁;onStart可见与onStop不可见;onResume可编辑(即焦点)与onPause;这6个方法是相对应的,那么就只剩下一个onRestart方法了,这个方法在Activity被onStop后,但是没有被onDestroy,在再次启动此Activity时就调用onRestart(而不再调用onCreate)方法;如果被onDestroy了,则是调用onCreate方法。

14. 两个Activity之间跳转时必然会执行的是哪几个方法。
一般情况比如说有两个activity,分别叫A,B ,当在A里面激活B组件的时候, A会调用onPause()方法,然后B调用onCreate(),onStart(),OnResume(),这个时候B覆盖了窗体,A会调用onStop()方法。如果B是透明的,或者是对话框的样式, 就不会调用onStop()方法。

15.横竖屏切换时候Activity的生命周期。
1、不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次。
2、设置Activity的android:configChanges="orientation"时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次。
3、设置Activity的android:configChanges="orientation|keyboardHidden"时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法。

16. 如何将一个Activity设置成窗口的样式。
在AndroidManifest.xml文件当中设置当前activity的一个属性:android:theme="@android:style/Theme.Dialog"
 
17. 你后台的Activity被系统 回收怎么办?如果后台的Activity由于某原因被系统回收可了,如何在被系统回收之前保存当前状态?
除了在栈顶的activity,其他的activity都有可能在内存不足的时候被系统回收,一个activity越处于栈底,被回收的可能性越大.
protected void onSaveInstanceState(Bundle outState) {
       super.onSaveInstanceState(outState);
       outState.putLong("id", 1234567890);
}
public void onCreate(Bundle savedInstanceState) {
//判断 savedInstanceState是不是空.
//如果不为空就取出来
        super.onCreate(savedInstanceState);
}

18. 如何退出Activity?如何安全退出已调用多个Activity的Application?
1、抛异常强制退出:
该方法通过抛异常,使程序Force Close。
验证可以,但是,需要解决的问题是,如何使程序结束掉,而不弹出Force Close的窗口。
2、记录打开的Activity:
每打开一个Activity,就记录下来。在需要退出时,关闭每一个Activity即可。
3、发送特定广播:
在需要结束应用时,发送一个特定的广播,每个Activity收到广播后,关闭即可。
4、递归退出
在打开新的Activity时使用startActivityForResult,然后自己加标志,在onActivityResult中处理,递归关闭。
上面是网上的一些做法.
其实,可以通过intent的flag来实现。intent.setFlag(FLAG_ACTIVITY_CLEAR_TOP)激活一个新的activity,然后在新的activity的oncreate方法里面 finish掉.
 
19. service是否在main thread中执行, service里面是否能执行耗时的操作?
默认情况,如果没有显示的指定service所运行的进程, Service和activity是运行在当前app所在进程的main thread(UI主线程)里面

20. 两个Activity之间怎么传递数据?
基本数据类型可以通过Intent传递数据 extras.putDouble(key, value) ;intent.putExtras(extras)
Application全局里面存放对象,自己去实现自己的application的这个类,基础系统的application , 每个activity都可以取到。
让对象实现implements Serializable 接口把对象存放到文件上。
让类实现Serializable 接口,然后可以通过 ObjectOutputStream ObjectInputStream
       //ObjectInputStream
       //ObjectOutputStream
           FileOutputStream fos = new FileOutputStream(new File("/sdcard/studnet.obj"));
           ObjectOutputStream oos = new ObjectOutputStream(fos);
           oos.writeObject(new Student());
 
21. 怎么让在启动一个Activity是就启动一个service?
在activity的onCreate()方法里面startService();

22. 同一个程序,但不同的Activity是否可以放在不同的Task任务栈中?
可以放在不同的Task中。需要为不同的activity设置不同的affinity属性,启动activity的Intent需要包含FLAG_ACTIVITY_NEW_TASK标记。

23. Activity怎么和service绑定,怎么在activity中启动自己对应的service?
bindService().  让activity能够访问到 service里面的方法构建一个intent对象,
Intent service = new Intent(this,MyService.class);
通过bindService的方法去启动一个服务,ServiceConnection 对象(重写onServiceConnected
和OnServiceDisconnected方法)和BIND_AUTO_CREATE.
       private class myconn implements ServiceConnection
       {
              public void onServiceConnected(ComponentName name, IBinder service) {
                     // TODO Auto-generated method stub
                     //可以通过IBinder的对象 去使用service里面的方法
              }
              public void onServiceDisconnected(ComponentName name) {
                     // TODO Auto-generated method stub
              }
       }

24. 什么是Service以及描述下它的生命周期。Service有哪些启动方法,有什么区别,怎样停用Service?
在Service的生命周期中,被回调的方法比Activity少一些,只有onCreate, onStart, onDestroy,onBind和onUnbind。
通常有两种方式启动一个Service,他们对Service生命周期的影响是不一样的。
1、通过startService
    Service会经历 onCreate 到onStart,然后处于运行状态,stopService的时候调用onDestroy方法。
    如果是调用者自己直接退出而没有调用stopService的话,Service会一直在后台运行。
2、通过bindService  
    Service会运行onCreate,然后是调用onBind, 这个时候调用者和Service绑定在一起。调用者退出了,Srevice就会调用onUnbind->onDestroyed方法。
    所谓绑定在一起就共存亡了。调用者也可以通过调用unbindService方法来停止服务,这时候Srevice就会调用
onUnbind->onDestroyed方法。
需要注意的是如果这几个方法交织在一起的话,会出现什么情况呢?
一个原则是Service的onCreate的方法只会被调用一次,就是你无论多少次的startService又bindService,Service只被创建一次。
如果先是bind了,那么start的时候就直接运行Service的onStart方法,如果先是start,那么bind的时候就直接运行onBind方法。
如果service运行期间调用了bindService,这时候再调用stopService的话,service是不会调用onDestroy方法的,service就stop不掉了,只能先UnbindService, 再StopService。
如果一个service通过startService 被start之后,多次调用startService 的话,service会多次调用onStart方法。多次调用stopService的话,service只会调用一次onDestroyed方法。
如果一个service通过bindService被start之后,多次调用bindService的话,service只会调用一次onBind方法。
多次调用unbindService的话会抛出异常。

25. 不用service,B页面为音乐播放,从A跳转到B,再返回,如何使音乐继续播放?
这个问题问的很山寨.默认不做任何处理,B里面的音乐都能播放。遇到问题, 可以随机应变,灵活发挥,多考虑些细节,比如说这个题就可以这样说,说说你对startActivityForResult的理解(),A开启B的时候,用startActivityForResult()方法, B返回的时候把播放的状态信息返回给A ,A继续播放音乐。

26. 什么是IntentService?有何优点?
异步处理服务。优点是Acitivity的进程,当处理Intent的时候,会产生一个对应的Service。Android的进程处理器现在会尽可能的不kill掉你。非常容易使用。
 
27. 什么时候使用Service?
拥有service的进程具有较高的优先级。官方文档告诉我们,Android系统会尽量保持拥有service的进程运行,只要在该service已经被启动(start)或者客户端连接(bindService)到它。当内存不足时,需要保持,拥有service的进程具有较高的优先级。
1.如果service正在调用onCreate,  onStartCommand或者onDestory方法,那么用于当前service的进程相当于前台进程以避免被killed。
2.如果当前service已经被启动(start),拥有它的进程则比那些用户可见的进程优先级低一些,但是比那些不可见的进程更重要,这就意味着service一般不会被killed.
3.如果客户端已经连接到service (bindService),那么拥有Service的进程则拥有最高的优先级,可以认为service是可见的。
4.如果service可以使用startForeground(int, Notification)方法来将service设置为前台状态,那么系统就认为是对用户可见的,并不会在内存不足时killed。
如果有其他的应用组件作为Service,Activity等运行在相同的进程中,那么将会增加该进程的重要性。
       1.Service的特点可以让他在后台一直运行,可以在service里面创建线程去完成耗时的操作.
       2.Broadcast receiver捕获到一个事件之后,可以起一个service来完成一个耗时的操作.
       3.远程的service如果被启动起来,可以被多次bind, 但不会重新create.  索爱手机X10i的人脸识别的service可以被图库使用,可以被摄像机,照相机等程序使用.
 
28. 请描述一下Intent 和 Intent Filter。
Intent在Android中被翻译为"意图",熟语来讲就是目的,他们是三种应用程序基本组件—activity,service和broadcast receiver之间互相激活的手段。 在调用Intent名称时使用ComponentName也就是类的全名时为显示调用。
这种方式一般用于应用程序的内部调用,因为你不一定会知道别人写的类的全名。我们来看看隐式Intent怎么用? 
首先我们先配置我们的Activity的Intent Filter  
<intent-filter>      
<action android:name="com.example.project.SHOW_CURRENT" /> 
</intent-filter>  
这样在调用的时候指定Intent的action,系统就是自动的去对比是哪个intent-filter符合我们的Activity,找到后就会启动Activity。  一个intent filter是IntentFilter类的实例, 但是它一般不出现在代码中,而是出现在android Manifest文件中, 以<intent-filter>的形式. (有一个例外是broadcast receiver的intent filter是使用Context.registerReceiver()来动态设定的, 其intent filter也是在代码中创建的.) 一个filter有action, data,category等字段. 一个隐式intent为了能被某个intent filter接受, 必须通过3个测试. 一个intent为了被某个组件接受, 则必须通过它所有的intent filter中的一个. 
 
29. Intent传递数据时,可以传递哪些类型数据?
基本类型可以传的,还有类是可以的,不过要继承Serializable这个接口。
Intent间传送数据一般有两种常用的办法:
1.extra
2.data. 
extra可以用Intent.putExtra放入数据。新启动的Activity可用Intent.getExtras取出来Bundle, 然后用Bundles.getLong, getInt, getBoolean, getString等函数来取放进入的值。
而data则是传输url。url可以是指我们熟悉的http, ftp 等网络地址,也可以指content来指向ContentProvider提供的资源。Intent.setData可以放入数据,Intent.getData可以取出数据。

30. 说说Activity,Intent,Service是什么关系。
一个Activity通常是一个单独的屏幕,每一个Activity都被实现为一个单独的类,这些类都是从Activity基类中继承来的,Activity类会显示由视图控件组成的用户接口,并对视图控件的事件做出响应。
Intent的调用是用来进行架构屏幕之间的切换的。Intent是描述应用想要做什么。Intent数据结构中两个最重要的部分是动作和动作对应的数据,一个动作对应一个动作数据。
Android Service是运行在后台的代码,不能与用户交互,可以运行在自己的进程,也可以运行在其他应用程序进程的上下文里。需要通过某一个Activity或者其他Context对象来调用。
Activity跳转到Activity,Activity启动Service,Service打开Activity都需要Intent表明跳转的意图,以及传递参数,Intent是这些组件间信号传递的承载者。

转载请注明出处:http://blog.csdn.net/iwanghang/

欢迎移动开发爱好者交流
沈阳或周边城市公司有意开发Android,请与我联系
联系方式



微信:iwanghang
QQ:413711276
邮箱:iwanghang@qq.com

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: