IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 2020大厂面试集合,GitHub,百度,flutter下拉加载 -> 正文阅读

[移动开发]2020大厂面试集合,GitHub,百度,flutter下拉加载

由于Fragment的生命周期与Activity的生命周期有着牵扯,所以把两者的图放到一起作为对比理解。

[图片上传失败…(image-a13b49-1601037655916)]

接下来就不同情况下的Fragment生命周期做一简单介绍:

Fragment在Activity中replace

新替换的Activity:onAttach() —> onCreate() —> onCreatView() —> onViewCreated —> onActivityCreated() —> onStart —>onResume()

被替换的Activity:onPause() —> onStop() —> onDestoryView() —> onDestory() —> onDetach()

Fragment在Activity中replace,并addToBackStack

新替换的Fragment(没有在BackStack中):onAttach?> onCreate >?onCreateView >?onViewCreated >?onActivityCreated >?onStart >?onResume

新替换的Fragment(已经在BackStack中):onCreateView > onViewCreated > onActivityCreated > onStart > onResume

被替换的Fragment:onPause > onStop > onDestroyView

Fragment在ViewPager中切换

我们称切换前的的Fragment称为PreviousFragment,简称PF;切换后的Fragment称为NextFragment,简称NF;其他Fragment称为OtherFragment,简称OF。

(在ViewPager中setUserVisibleHint能反映出Fragment是否被切换到后台或前台,所以在这里也当作生命周期)

  • 如果相关的Fragment没有被加载过:

NF: setUserVisibleHint(false)【用户不可见】 > onAttach > onCreate > setUserVisibleHint(true)【用户可见】 > onCreateView > onViewCreated > onActivityCreated > onStart > onResume

OF跟NF相邻: setUserVisibleHint(false) > onAttach > onCreate > onCreateView > onViewCreated > onActivityCreated > onStart > onResume

  • 如果相关的Fragment已经被加载过:

NF跟PF相邻? :setUserVisibleHint(true)

NF跟PF不相邻:setUserVisibleHint(true)?> onCreateView > onViewCreated > onActivityCreated > onStart > onResume

PF跟NF相邻? :setUserVisibleHint(false)

PF跟NF不相邻:setUserVisibleHint(false) > onPause > onStop > onDestroyView

OF跟PF相邻:onPause > onStop > onDestroyView

OF跟NF相邻:onCreateView > onViewCreated > onActivityCreated > onStart > onResume

OF夹在PF和NF中间:不调用任何生命周期方法

NF跟PF相邻? :setUserVisibleHint(true)

NF跟PF不相邻:setUserVisibleHint(true)?> onCreateView > onViewCreated > onActivityCreated > onStart > onResume

PF跟NF相邻? :setUserVisibleHint(false)

PF跟NF不相邻:setUserVisibleHint(false) > onPause > onStop > onDestroyView

OF跟PF相邻:onPause > onStop > onDestroyView

OF跟NF相邻:onCreateView > onViewCreated > onActivityCreated > onStart > onResume

OF夹在PF和NF中间:不调用任何生命周期方法

  • 如果重写了FragmentPagerAdapter的DestroyItem方法,并且相关的Fragment已经加载过:

相互切换时只会调用setUserVisibleHint

Fragment进入了运行状态:

Fragment在进入运行状态时,以下四个生命周期会随它所属的Activity一起被调用:

onPause() —> onStop() —> onStart() —> onResume()

关于Fragment的onActivityResult方法:

使用Fragment的startActivity方法时,FragmentActivity的onActivityResult方法会回调相应的Fragment的onActivityResult方法,所以在重写FragmentActivity的onActivityResult方法时,注意调用super.onActivityResult。

8、?如何实现Fragment的滑动?

将Fragment与viewpager绑定,通过viewpager中的touch事件,会进行move事件的滑动处理。

Fragment布局

Fragment代码:

public class FragmentOne extends Fragment { @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_one, container, false); }}

public class FragmentTwo extends Fragment { @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_Two, container, false); }}

viewpager布局:

xmlns:tools=“http://schemas.android.com/tools” android:layout_width=“match_parent” android:layout_height=“match_parent” tools:context=“com.example.spreadtrumshitaoli.fragmentscroll.MainActivity”> <android.support.v4.view.ViewPager android:id="@+id/view_pager" android:layout_height=“match_parent” android:layout_width=“match_parent”/> </android.support.constraint.ConstraintLayout>

MainActivity代码:

public class MainActivity extends AppCompatActivity { private FragmentOne fragmentOne; private FragmentTwo fragmentTwo; private ViewPager viewPager; private ArrayList mFragmentList = new ArrayList (); private FragmentPagerAdapter fragmentPagerAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); init(); } private void init() { viewPager = (ViewPager) findViewById(R.id.view_pager); fragmentOne = new FragmentOne(); fragmentTwo = new FragmentTwo(); mFragmentList.add(fragmentOne); mFragmentList.add(fragmentTwo); //将adapter和fragment绑定在一起。 fragmentPagerAdapter = new FragmentPagerAdapter(getSupportFragmentManager()) { @Override public Fragment getItem(int i) { return mFragmentList != null ? mFragmentList.get(i) : null; } @Override public int getCount() { return mFragmentList != null ? mFragmentList.size() : 0; } }; viewPager.setAdapter(fragmentPagerAdapter); viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int i, float v, int i1) { } @Override public void onPageSelected(int i) { //TODO: } @Override public void onPageScrollStateChanged(int i) { } }); } }

在这段代码中,我们

首先fragment以及viewpager都实例化;

再将fragment添加到泛型arraylist里;

最后将带有fragment的arraylist和adapter绑定。

9、fragment之间传递数据的方式?

方法一:

  • 1、在MainFragment中设置一个setData()方法,在方法中设置更改按钮名称;

    1. //MainFragment.java文件中

    2. public void setData(String string) {

    3. bt_main.setText(string);

    4. }

  • 2、在MenuFragment中的ListView条目点击事件中通过标签获取到MainFragment,并调用对应的setData()方法,将数据设置进去,从而达到数据传递的目的。

    1. lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {

    2. @Override

    3. public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

    4. MainFragment mainFragment =

    5. (MainFragment) getActivity()

    6. .getSupportFragmentManager()

    7. .findFragmentByTag("mainFragment");

    8. mainFragment.setData(mDatas.get(position));

    9. }

    10. });

    只需上面区区两步即可达到数据传递的目的。
    

方法二:
采取接口回调的方式进行数据传递。

  • step1: 在Menuragment中创建一个接口以及接口对应的set方法:

    1. //MenuFragment.java文件中

    2. public interface OnDataTransmissionListener {

    3. public void dataTransmission(String data);

    4. }

    5. public void setOnDataTransmissionListener(OnDataTransmissionListener mListener) {

    6. this.mListener = mListener;

    7. }

  • step2: 在MenuFragment中的ListView条目点击事件中进行接口进行接口回调

    1. //MenuFragment.java文件中

    2. lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {

    3. @Override

    4. public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

    5. /**

    6. * 方法二:采取接口回调的方式进行数据传递

    7. */

    8. if (mListener != null) {

    9. mListener.dataTransmission(mDatas.get(position));

    10. }

    11. }

    12. });

  • step3: 在MainActivity中根据menuFragment获取到接口的set方法,在这个方法中进行进行数据传递,具体如下:

    1. //在MainActivity.java中

    2. menuFragment.setOnDataTransmissionListener(new MenuFragment.OnDataTransmissionListener() {

    3. @Override

    4. public void dataTransmission(String data) {

    5. mainFragment.setData(data); //注:对应的mainFragment此时应该要用final进行修饰

    6. }

    7. });

      通过上面的三步也可以轻松做到Fragment数据之间的传递。


方法三:
使用三方开源框架:EventBus
那么问题来了:EventBus是个啥东西???
简单来说,EventBus是一款针对Android优化的发布/订阅(publish/subscribe)事件总线。主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service,线程之间传递消息。简化了应用程序内各组件间、组件与后台线程间的通信。优点是开销小,代码更优雅,以及将发送者和接收者解耦。比如请求网络,等网络返回时通过Handler或Broadcast通知UI,两个Fragment之间需要通过Listener通信,这些需求都可以通过EventBus实现。
下面我们就用EventBus来实现以下Fragment之间的数据传递:

  • step1:引入EventBus
compile 'org.greenrobot:eventbus:3.0.0'
  • step2:注册事件接收者
    这里MainFragment是要接收MenuFragment发送来的数据,所以我们在MainFragment中的onCreateView()方法中进行注册:
EventBus.getDefault().register(this);
  • step3:发送事件
    注:发送事件之前其实还有一步定义事件类型,这里我们传递的数据只有一个类型,所以这一步取消了。
    MenuFragment发送数据给MainFragment,所以我们在MenuFragment中将要传递的数据进行发送事件操作:

    1. lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {

    2. @Override

    3. public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

    4. EventBus.getDefault().post(mDatas.get(position));

    5. }

    6. });

  • step4:接收消息并处理
    在MainFragment中我们接收来自MenuFragment传递过来的数据,并进行对应的处理(注:EventBus 3.0版本这一步必须要写注解@Subscribe (与2.4版本有所区别)):

    1. @Subscribe

    2. public void onEvent(String data) {

    3. bt_main.setText(data);

    4. }

      通过上面这一步即可完成数据之间的传递,需要注意的是在销毁的时候我们要注销事件接收。

  • step5:注销事件接收

    1. //MainFragment.java中

    2. @Override

    3. public void onDestroy() {

    4. super.onDestroy();

    5. EventBus.getDefault().unregister(this);

    6. }

      以上五步完成了Fragment之间的数据传递,看似比上面两个方法要复杂的多,但当我们涉及到复杂的Fragment之间数据传递(例如Fragment中嵌套多层Fragment)时,就会体会到EventBus的爽快之处~~~这里不进行赘述了。

10、Activity 怎么和Service 绑定?

这需要实现service中的onBind()函数以返回service实例给activity

1、创建service类和activity类。

2、在service类中定义一个内部类继承自Binder()类:

public?class?MyBinder?extends?Binder{

public?Service1?getService(){

return?Service1.this;

}

} ?
实例化onBind()方法:

private final IBinder binder = new MyyBinder();

@Override

public IBinder onBind(Intent intent){

Log.i(LOG,“onBind…”);

return binder;

}

3、在activity中完成绑定

Intent intent = new Intent(Activity1.this,Activity2.class);

bindService(intent,conn,Context.BIND_AUTO_CREATE);

  • bindService的第二个参数是一个ServiceConnection类型的参数。service和其他组件之间的连接都表示为一个ServiceConnection,要想将service和其他组件进行绑定,就需要实现一个新的ServiceConnection。

public?ServiceConnection?conn=?new?ServiceConnection()?{

@Override

public?void?onServiceDisconnected(ComponentName?name)?{

//当连接意外断开时调用

Log.i(LOG,?“onServiceDisconnected>>>>>>>>”);

myservice?=?null;

}

@Override

public?void?onServiceConnected(ComponentName?name,?IBinder?service)?{

//当建立连接时调用

Log.i(LOG,?“onServiceConnected>>>>>>>>”);

myservice?=?((Service1.MyBinder)service).getService();

}

};

  • bindService的第三个参数是一个flag。

可以使用的flag有:

BIND_AUTO_CREATE:绑定完成后就启动目标service

BIND_DEBUG_UNBIND:这只在debug时使用,跟unbind有关。

BIND_NOT_FOREGROUND:确保被绑定的service永远不会有运行于前台的优先级,因为默认情况下,绑定一个service会提高它的优先级

BIND_ABOVE_CLIENT:确保客户端处于前台时,绑定的service也变

《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》

【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享

为前台进程

BIND_ALLOW_OOM_MANAGEMENT:允许系统在低内存等状态下删除该service(这是自己对源码中注释的理解)

BIND_WAIVE_PRIORITY:绑定service时不改变其优先级

BIND_ADJUST_WITH_ACTIVITY:系统根据service所绑定的activity的重要程度来调整这个service的优先级。

11、service生命周期?

1.??? 被启动的服务(startService())的生命周期。
???????????? 如果一个Service被某个Activity 调用Context.startService() 方法启动,那么不管是否有Activity使用bindService()绑定或unbindService()解除绑定到该Service,该Service都在后台运行。如果一个Service被多次执行startService(),它的onCreate()方法只会调用一次,也就是说该Service只会创建一个实例,而它的onStartCommand()将会被调用多次(对应调用startService()的次数)。该Service将会一直在后台运行,直到被调用stopService(),或自身的stopSelf方法。当然如果系统资源不足,系统也可能结束服务。
2.??? 被绑定的服务(bindService())的生命周期。
???????????? 如果一个Service被调用?Context.bindService ()方法绑定启动,不管调用bindService()调用几次,onCreate()方法都只会调用一次,而onStartCommand()方法始终不会被调用,这时会调用onBind()方法。当连接建立之后,Service将会一直运行,除非调用Context.unbindService() 断开连接或者之前调用bindService() 的 Context 不存在了(如该Activity被finish),系统将会自动停止Service,对应onDestroy()将被调用。
3.??? 被启动又被绑定的服务的生命周期。
?????????????如果一个Service又被启动又被绑定,则该Service将会一直在后台运行。调用unbindService()将不会停止Service,而必须调用stopService()或Service的stopSelf()方法来停止服务。
4.?? 当服务被停止时清除服务。
??????????? 当一个Service被终止时,Service的onDestroy()方法将会被调用,在这里应当做一些清除工作,如停止在Service中创建并运行的线程等。

12、 activity和service的绑定方式以及怎么在Activity 中启动自己对应的Service?

1、activity能进行绑定得益于Serviece的接口。为了支持Service的绑定,实现onBind方法。

2、Service和Activity的连接可以用ServiceConnection来实现。需要实现一个新的ServiceConnection,重现onServiceConnected和OnServiceDisconnected方法,一旦连接建立,就能得到Service实例的引用。

3、执行绑定,调用bindService方法,传入一个选择了要绑定的Service的Intent(显示或隐式)和一个你实现了的ServiceConnection的实例

13、Service的启动方式?

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

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

14、谈谈ContentProvider、ContentResolver、ContentObserver之间的关系?

ContentProvider:

  • 四大组件的内容提供者,主要用于对外提供数据

  • 实现各个应用程序之间的(跨应用)数据共享,比如联系人应用中就使用了ContentProvider,你在自己的应用中可以读取和修改联系人的数据,不过需要获得相应的权限。其实它也只是一个中间人,真正的数据源是文件或者SQLite等

  • 一个应用实现ContentProvider来提供内容给别的应用来操作,通过ContentResolver来操作别的应用数据,当然在自己的应用中也可以

ContentResolver:

  • 内容解析者,用于获取内容提供者提供的数据

  • ContentResolver.notifyChange(uri)发出消息

ContentObserver:

  • 内容监听器,可以监听数据的改变状态

  • 目的是观察(捕捉)特定Uri引起的数据库的变化,继而做一些相应的处理,它类似于数据库技术中的触发器(Trigger),当ContentObserver所观察的Uri发生变化时,便会触发它。触发器分为表触发器、行触发器,相应地ContentObsever也分为表ContentObserver、行ContentObserver,当然这是与它所监听的Uri MIME Type有关的

  • ContentResolver.registerContentObserver()监听消息

15、广播的分类?

分为有序广播和无序广播两类。

  • 无序广播发送代码:

public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void click(View v){ //启动界面 startActivity //发送广播 sendBroadcast Intent intent = new Intent(); intent.setAction(“com.itheima.cctv.action.NEWS”); intent.putExtra(“data”, “我是一个无须的广播”); sendBroadcast(intent); }}

  • 无序广播的监听代码:

public class CctvReceiver extends BroadcastReceiver { private static final String TAG = “CctvReceiver”; @Override public void onReceive(Context context, Intent intent) { String data = intent.getStringExtra(“data”); Log.d(TAG, “data===”+data); } }

  • 有序广播发送:
public class ShengReceiver extends BroadcastReceiver {     @Override    public void onReceive(Context context, Intent intent) {        Log.d("vivi", "我是省级部门,我收到的指令是:"+getResultData());        //getResultData()是用来获取有序广播里面的数值.这里的信息是:        //主席讲话:每人奖励10斤土豆          setResultData("主席讲话:每人奖励7斤土豆");//有序广播的数值,可以被修改,后面的程序在接受到这个广播,就会变成,现在我们改变的值了         //有序广播传输是可以终止的.但是最终的接受者就算在终止之后,也是可以接受到数据的        //abortBroadcast();    }}
public class ShiReceiver extends BroadcastReceiver {     @Override    public void onReceive(Context context, Intent intent) {        Log.d("vivi", "我是市级部门,我收到的指令是:"+getResultData());    //因为上面修改了数据,所以这里获取到的数据是:主席讲话:每人奖励7斤土豆    } }
<!--有序广播的优先级别使用 android:priority=""来指定,最高是1000,最低是-1000-->        <receiver android:name="com.itheima.region.ShengReceiver">            <intent-filter android:priority="1000">                <action android:name="com.itheima.gov.action.POTATO"/>            </intent-filter>        </receiver>         <receiver android:name="com.itheima.region.ShiReceiver">           <intent-filter android:priority="500">                <action android:name="com.itheima.gov.action.POTATO"/>            </intent-filter>        </receiver>

有序接收:

public class MyReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Log.d(“vivi”, “我是恩恩主席的内线,我收到的指令是:”+getResultData()); } }

启动模式:

1、standard:标准化启动模式

每启动一个Activity,都会重新创建Activity的新的实例,将其放在栈的顶部。不需要考虑这个实例是否已经存在。

每一次启动,它的onCreate()、onStart()、onResume()方法都会被依次调用。

2、singleTop:栈顶复用模式

当前栈中已经有该Activity实例,并且该实例位于栈顶时,会去调用onNewIntent()方法。

当前栈中已有该Activity的实例但是该实例不在栈顶时,依然会去创建Activity。

当前栈中不存在该Activity实例时,会去新创建一个该Activity。

应用场景:IM对话框、新闻客户端推送。

3、singleTask:栈内复用模式

它主要检测【寻找,通过taskAffinity】整个栈中是否已经存在当前想要启动的Activity,存在的话直接将该Activity置于栈顶,之前位于该Activity上面的Activity将被销毁,同时调用onNewIntent()方法,而不存在的话进行创建。

应用场景:应用主界面。

4、singleInstance:

一个人独享一个任务栈。当该Activity启动时,系统会创建一个新的任务栈,同时将Activity放到这个新的任务栈当中,有别的应用来启动该Activity时,由于栈内复用的特性,不会再去创建相应Activity任务栈,而是这两个应用独享一个Activity实例。

例如:应用A中现有两个Activity E、Activity F,为standard启动模式,应用B中有一个Activity G,但其启动模式是singleInstance。应用A想用应用B任务栈当中的Activity G,尽管在不同的应用下,但是应用A仍然会直接复用Activity G。

特性:

1、以SingleInstance模式启动的Activity具有全局唯一性【全局唯一性即指在整个系统当中只会存在一个这样的实例】;

2、如果在启动这样一个Activity时,【整个系统都是单例的】,已经存在了一个实例;

3、以SingleInstance模式启动的Activity具有独占性。

应用场景:呼叫来电。

问题:onNewIntent()调用时机?

  • singleTop:如果新Activity已经位于任务栈的栈顶,就不会重新创建,并回调?onNewIntent(intent)?方法。
  • singleTask:只要该Activity在一个任务栈中存在,都不会重新创建,并回调?onNewIntent(intent)?方法。

网络协议:

协议:【协议指计算机通信网络中两台计算机之间进行通信所必须共同遵守的规定或规则】

HTTP协议

基本概念:【超文本传输协议】允许将HTML(超文本标记语言)文档从Web服务器传送到客户端的浏览器。HTTP协议是 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 基于TCP/IP通信协议来传输数据的,可以从服务器端获取图片等数据资源。

URI:【uniform resource identifier】统一的资源标识符,用来唯一的标识一个资源。强调资源!!!

组成部分:

1)访问资源的命名机制;file

2)存放资源的主机名;

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章           查看所有文章
加:2021-12-05 12:09:21  更:2021-12-05 12:11:56 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 8:00:29-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码