阿里一面

一.Activity 和 Fragment

1)Activity 生命周期
onCreate - onStart - onResume (Activity运行)- onPause - onStop - onDestroy(Activity销毁)

2)Fragment生命周期
onAttach - onCreate - onCreateView - onViewCreated - onActivityCreated - onStart - onResume
- onPause - onStop -onDestroyView - onDestroy - onDetach

3)Activity和Fragment ,Fragment和 Fragment 是如何通信的

A.Fragment和Activity之间通信
https://blog.csdn.net/lmj623565791/article/details/37992017

Activity访问Fragment
 1、使用fragment标签直接构建的Fragment
 我们在所依附的Activity里可以通过 getFragmentManager()先获取FragmentManager对象
 再通过调用FragmentManager对象的 findFragmentByTag()和findFragmentById()得到Fragment对象
 再调用Fragment对象的getView()获取Fragment对应的View对象view
 最后再调用View的view.findViewById方法获取或者直接通过Fragment对象调用相关访问属性的方法。
   FragmentManager manager = getFragmentManager();
   TargetFragment targetFragment = (TargetFragment)manager.findFragmentById(R.id.id_fragment_showpic);

 2、动态Java代码构建的Fragment
 由于我们add时候会先用代码声明一个Fragment对象,所以我们可以跳过前面的2步,
 直接使用Fragment对象的getProperty()方法获取成员,其他的与静态构建Fragment相同

Fragment获取Activity控件
 --由于Fragment依附于Activity,属于Activity的一部分,并且拥有自己的View,
 所以我们通过getActivity()先得到依附的Activity对应的View,在通过view.findViewById()

 MainFragment.java:
 public class MainFragment extends Fragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    final View view=inflater.inflate(R.layout.fragment_main,null);
    Button button= (Button) view.findViewById(R.id.id_tofragment_btn);
    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            TextView textView=(TextView) getActivity().findViewById(R.id.id_content_edt);
            String txt=textView.getText().toString();
          Toast.makeText(getActivity(),txt,Toast.LENGTH_LONG).show();
        }
    });
    return view;
   }
}

B.Fragment1和 Fragment2
-首先获取到另一个Fragment2对象,然后直接在一个Fragment1中调用另一个Fragment2的public方法
通过宿主Activity获取到FragmentManager,然后在获取到另一个Fragment2的实例
ContentFragment cf = (ContentFragment) getActivity()
.getFragmentManager().findFragmentById(
R.id.content_fg);
cf.showPro(name);
这种方法适于那些我们在布局文件中就已经定义了的Fragment,这种Fragment每个都有id。
可以通过FragmentManager找到,但是如果我们使用了ViewPager,即每个Fragment都是动态添加进来的,
这个时候我们无法通过FragmentManager获得另外一个Fragment的实例

还有使用 广播 和使用接口 都可以实现Fragment之间,Activity和Fragment之间通信
    https://blog.csdn.net/u012702547/article/details/49786417

接口实现 
Fragment1 和 Fragment2之间通信
--有效的解决在一个Fragment中拿不到另一个Fragment实例的问题,
具体应用场景就是ViewPager中的Fragment之间通信。
-- 1.Fragment1定义一个接口 showPro

 public interface showPro {  
   public void showProByName(String name);  
 } 

-- 2 定义一个变量
 private showPro mCallback;  

-- 3 在宿主Activity实现这个接口 showPro
 public class MainActivity extends Activity implements showPro {  

 private ContentFragment cf;  

 @Override  
 protected void onCreate(Bundle savedInstanceState) {  
    super.onCreate(savedInstanceState);  
    setContentView(R.layout.activity_main);  
    getActionBar().hide();  
    cf = (ContentFragment) getFragmentManager().findFragmentById(  
            R.id.content_fg);  
 }    

 @Override  
 public void showProByName(String name) {  
    cf.showPro(name);  
 }  
}  
-- 4 当Fragment调用onAttach方法时我们就可以实例化这个接口 showPro
  @Override  
 public void onAttach(Activity activity) {  
  super.onAttach(activity);  
  if (activity != null) {  
    mCallback = (showPro) activity;  
  }  
}  

广播实现 
-- 1 不论我们有没有用ViewPager,都可以用广播实现两个Fragment之间的通信,
  广播算是这里最灵活的通信方式了,我们看看在左边Fragment1中发送广播:

  Intent intent = new Intent("showPro");  
                intent.putExtra("name", name);  
                LocalBroadcastManager.getInstance(getActivity())  
                        .sendBroadcast(intent);



-- 2 右边Fragment2中接收广播:

 LocalBroadcastManager localBroadcastManager = LocalBroadcastManager  
    .getInstance(getActivity());  
 IntentFilter intentFilter = new IntentFilter();  
 intentFilter.addAction("showPro");  
 BroadcastReceiver br = new BroadcastReceiver() {  

  @Override  
  public void onReceive(Context context, Intent intent) {  
    String key = intent.getStringExtra("name");  
    list = map.get(key);  
    adapter = new ArrayAdapter<String>(getActivity(),  
            android.R.layout.simple_list_item_1, list);  
    lv.setAdapter(adapter);  
    }  

 };  
 localBroadcastManager.registerReceiver(br, intentFilter); 

4)为什么要用Fragment

Fragment优点
 对页面逻辑解耦带来了极大的方便。其拥有自己的生命周期,便于我们来控制和管理页面的状态变化
 Fragment可以使你能够将activity分离成多个可重用的组件,每个都有它自己的生命周期和UI。
 Fragment可以轻松得创建动态灵活的UI设计,可以适应于不同的屏幕尺寸。从手机到平板电脑。

 Fragment是一个独立的模块,紧紧地与activity绑定在一起。可以运行中动态地移除、加入、交换等。

 Fragment提供一个新的方式让你在不同的安卓设备上统一你的UI。

 Fragment 解决Activity间的切换不流畅,轻量切换。

 Fragment 替代TabActivity做导航,性能更好。

 Fragment 在4.2.版本中新增嵌套fragment使用方法,能够生成更好的界面效果。

 Fragment做局部内容更新更方便,原来为了到达这一点要把多个布局放到一个activity里面,现在可以用多Fragment来代替,
 只有在需要的时候才加载Fragment,提高性能。

 可以从startActivityForResult中接收到返回结果,但是View不能

二 Service
1) 为什么要用service
Service是用于后台服务的,当应用程序被挂到后台的时候,为了保证应用某些组件仍然可以工作而引入了Service这个概念。
Service不是独立的进程,也不是独立的线程,它是依赖于应用程序的主线程的,也就是说,
在更多时候不建议在Service中编写耗时的逻辑和操作,否则会引起ANR,

2) IntentService是什么
IntentService是继承Service的,是为了解决在Service进行耗时操作会引起ANR,引入的
IntentService包含Service的全部特性,包含生命周期
与service不同的是在执行onCreate操作的时候,会内部开启一个线程,去执行耗时操作
IntentService 异步处理服务,新开一个线程,HandlerThread在线程发消息,处理完成后,清理线程,关闭服务

3)生命周期

三 Broadcast
1)本地广播的含义
LocalBroadcastmanager.sendBroadcast(Intent),只在app内传播

四 开源框架
1)EventBus
EventBus是一个消息总线,以观察者模式实现,用于简化程序的组件,县城铜线,可以轻易切换线程,开辟线程
基本使用
1 自定义一个类
2 在接收界面注册
3 发送消息
4 接收消息的界面
5 解除注册

五 原理问题

1) library module可以有assets文件夹么
2) 为什么要是XML,Json和XML的区别
3) 图片加载,三级缓存,第三级在网络层,如何加载大图片
4) 线程池

Java相关

一 JVM内存模型
1 程序计数器(Program Counter Register)
2 Java虚拟机栈(Java Stack)
3 本地方法栈(Native Method Stack)
4 堆(Heap)
5 方法区(Method Area)

二 Android 内存泄露,举例几个容易发生内存泄露的场景;
1)定义
–指程序申请内存后,无法释放已经申请的内存空间

2)出现内存泄露的场合及解决方案
–Activity 中handler间断的post消息,会造成activity泄露


1)子类可以继承父类的静态方法和静态变量么? 子类父类同名静态方法存在“重写”关系么?

–1 . 子类可以继承父类的静态方法和静态变量。因为Static修饰的方法和变量属于类本身,
子类可以访问父类的静态方法和变量,但是前提父类不被Private修饰,对子类是可见的
–2 . 因为Static修饰的方法和变量属于类本身,子类 和 父类中同名的静态变量和方法 都是相互独立的,属
于各自类本身的。不存在重写 呈现多态特性。

2)final 含义,修饰数据,参数 方法 类 的意义?

final修饰数据
– 1 一个永不改变的编译时常量
2 一个在运行时被初始化的值,不希望它被改变
3 final修饰说明它是一个常量,static修饰则强调只有一份
4 final static修饰的基本类型全用大写字母命名,之间用下划线隔开
final 修饰参数
– 可以读取参数,不能修改参数数值
final 修饰方法
– 锁定方法,保证继承类无法覆盖该方法
final 修饰方法
– 不能有子类继承该类
final修饰数据 – 1 一个永不改变的编译时常量
2 一个在运行时被初始化的值,不希望它被改变 3 final修饰说明它是一个常量,static修饰则强调只有一份 4 final static修饰的基本类型全用大写字母命名,之间用下划线隔开 final 修饰参数 –
可以读取参数,不能修改参数数值 final 修饰方法 – 锁定方法,保证继承类无法覆盖该方法 final 修饰方法
– 不能有子类继承该类

3)使用的集合有哪些?
4)多线程并发机制

多线程实现的两种方式:
–通过实现java.lang.Runnale接口
–通过扩展java.lang.Thread类
1.实现Runnable

public interface Runnable {
        void run();
     }

a.创建一个实现Runnable接口的类,该类的对象是一个Runnable对象
b.创建一个Thread类型的对象,并将Runnable对象作为参数传入到Thread的构造函数中
于是这个Thread对象包含一个 实现了run()方法的Runnable对象
c.调用上一步创建的Thread对象的start方法。

public class RunnableThreadExample implements Runnable {
        public int count = 0;

        public void run() {
            System.out.println("RunnableThread strting");
            try {
                while(count < 5) {
                    Thread.sleep(500);
                    count++;
                }
            } catch(InterruptedException exc) {
                System.out.println("RunnableThread interrupted");
            }
            System.out.println("RunnThread terminating");
        }
      } 

      public static void main(String[] args) {
        RunnableThreadExample instance = new RunnableThreadExample;
        Thread thread = new Thread(instance);
        thread.start();

        while(instance.count !=3) {
            try{
                Thread.sleep(250);
            } catch (InterruptedException exc) {
                exc.printStackTrace();
            }
        }
      }

2 扩展Thread类

5)死锁

a.定义
–第一个线程在等待第二个线程持有的某个资源,而第二个线程又在等待第一个线程持有的对象资源
(或者两个以上县城形成的类似情形)。由于每个线程都在等待其他线程释放资源,导致每个线程都会
一直等下去,于是这些线程就陷入了死锁。

b.死锁产生的四个条件
– 1 互斥
某个时刻只有一个线程能访问某个资源
2 持有并等待
一个进程已经持有某一资源,不用释放当前拥有的资源,就能要求获得更多资源
3 没有抢占
一个进程不能强制另一个进程释放资源
4 循环等待
两个或两个以上进程形成循环链,每个进程都在等待循环链中的另一个进程持有的资源

6)网络相关
7)常用设计模式

数据结构
一 链表
1)如何判断单链表相交

猜你喜欢

转载自blog.csdn.net/Ghost_tal/article/details/80284304