当前位置: 移动技术网 > IT编程>移动开发>Android > 详解android webView独立进程通讯方式

详解android webView独立进程通讯方式

2019年07月24日  | 移动技术网IT编程  | 我要评论

霹雳赛车游戏下载,茶叶批发网,青岛论坛

为什么需要将webview放在独立进程

  • webview 加载网页的时候可能占用大量内存,导致应用程序oom。
  • webview 在访问结束的时候可以直接杀死该进程,防止内存泄漏。
  • webview 在崩溃的时候不影响主进程。

webview独立进程需要注意什么

  • 由于进程之间内存是独立的,所以导致了appcation, 静态类需要在新的进程重新创建。
  • 内存中的数据不共享,需要跨进程通讯。

如何声明一个独立进程

在默认情况下,同一应用的所有组件都在相同的进程中运行。
在manifest中可以设置各组件 (<activity>、<service>、<receiver>、<provider>)的 android:process 属性来指定相应的进程。

跨进程的方式

在android当中提供了2种方式实现。

一种是messenger, 另一种是aidl.

  • messenger:实现相对简单,将所有请求放到消息队列中,不适合做并发处理,在大多数的场景用messenger就可以实现了。
  • aidl: 适合并发操作。直接方法调用,结构更清晰。

messenger

由于messenger是采用消息队列的方式实现,所有接受和发送的时候都需要handler协助。

服务端

public class messengerservice extends service {
  
  public static final int get_data = 1;
  public static final int set_data = 2;
  
  messenger messenger = new messenger(new servicehandler());
  messenger replymessenger; //向客服端返回信息
  public messengerservice() {
  }
  
  @override
  public ibinder onbind(intent intent) {
    return messenger.getbinder();
  }
  
  
  class servicehandler extends handler {
    @override
    public void handlemessage(message msg) {
      replymessenger = msg.replyto;
      switch (msg.what) {
        case get_data:
          //客服端向服务端请求数据
          if (replymessenger != null) {
            bundle bundle = new bundle();
            bundle.putstring("str", customdata.getinstance().getdata());
            message message = message.obtain(null, 1);
            message.setdata(bundle);
            try {
              replymessenger.send(message);
            } catch (remoteexception e) {
              e.printstacktrace();
            }
          }
          break;
        case set_data:
          //客服端向服务端请求更新数据
          customdata.getinstance().setdata(msg.getdata().getstring("str"));
          break;
      }
    }
  }
}

客服端:

public class messengerclientactivity extends appcompatactivity {
  
  private webview mwebview;
  private button mgetdatbtn;
  private button msetdatbtn;
  
  public static void startthis(context context, string url) {
    intent intent = new intent(context, messengerclientactivity.class);
    intent.putextra("url", url);
    context.startactivity(intent);
  }
  
  @override
  protected void oncreate(bundle savedinstancestate) {
    super.oncreate(savedinstancestate);
    setcontentview(r.layout.activity_messenger_client);
    mwebview = (webview) findviewbyid(r.id.webview);
    mgetdatbtn = (button) findviewbyid(r.id.get_data_btn);
    msetdatbtn = (button) findviewbyid(r.id.set_data_btn);
        
    websettings websettings = mwebview.getsettings();
    websettings.setjavascriptenabled(true);
    websettings.setjavascriptcanopenwindowsautomatically(true);
    websettings.setsupportzoom(false);
    websettings.setbuiltinzoomcontrols(false);
    websettings.setallowfileaccess(true);
    websettings.setdatabaseenabled(true);
    websettings.setdomstorageenabled(true);
    websettings.setgeolocationenabled(true);
    websettings.setappcacheenabled(true);
    websettings.setappcachepath(getapplicationcontext().getcachedir().getpath());
    websettings.setdefaulttextencodingname("utf-8");
    //屏幕自适应
    websettings.setusewideviewport(true);
    websettings.setloadwithoverviewmode(true);
    if (build.version.sdk_int >= build.version_codes.kitkat) {
      websettings.setcachemode(websettings.load_cache_else_network);
    } else {
      websettings.setcachemode(websettings.load_default);
    }
    if (build.version.sdk_int >= build.version_codes.honeycomb) {
      websettings.setdisplayzoomcontrols(false);
    }
    if (build.version.sdk_int >= build.version_codes.kitkat) {
      websettings.setloadsimagesautomatically(true);
    } else {
      websettings.setloadsimagesautomatically(false);
    }
    
    mwebview.setscrollbarstyle(webview.scrollbars_inside_overlay);
    mwebview.sethorizontalscrollbarenabled(false);
    mwebview.sethorizontalfadingedgeenabled(false);
    mwebview.setverticalfadingedgeenabled(false);
    
    string url = "http://www.jianshu.com/";
    mwebview.loadurl(url);

    mgetdatbtn.setonclicklistener(new view.onclicklistener() {
      @override
      public void onclick(view v) {
        getdata();
      }
    });
    
    msetdatbtn.setonclicklistener(new view.onclicklistener() {
      @override
      public void onclick(view v) {
        setdata();
      }
    });
  }
  
  messenger messenger;
  messenger messengerreply = new messenger(new handler() {
    @override
    public void handlemessage(message msg) {
      switch (msg.what) {
        case messengerservice.get_data:
          mgetdatbtn.settext("" + msg.getdata().get("str"));
          break;
      }
    }
  });
  boolean mbound;
  serviceconnection serviceconnection = new serviceconnection() {
    @override
    public void onserviceconnected(componentname name, ibinder service) {
      messenger = new messenger(service);
      mbound = true;
    }
  
    @override
    public void onservicedisconnected(componentname name) {
      messenger = null;
      mbound = false;
    }
    
  };
  
  private void getdata() {
    if (!mbound) return;
    message message = message.obtain(null, messengerservice.get_data, 0,0);
    //用于服务端应答
    message.replyto = messengerreply;
    sendmessage(message);
  }
  
  private void setdata() {
    if (!mbound) return;
    message message = message.obtain(null, messengerservice.set_data, 0,0);
    sendmessage(message);
  }
  
  private void sendmessage(message message) {
    try {
      messenger.send(message);
    } catch (remoteexception e) {
      e.printstacktrace();
    }
  }
  
  
  @override
  protected void onstart() {
    super.onstart();
    // bind to the service
    bindservice(new intent(this, testwebservice.class), serviceconnection,
        context.bind_auto_create);
  }
  
  @override
  protected void onstop() {
    super.onstop();
    // unbind from the service
    if (mbound) {
      unbindservice(serviceconnection);
      mbound = false;
    }
  }
  
  private void destroywebview(webview webview) {
    if (webview == null)
      return;
    webview.stoploading();
    viewparent viewparent = webview.getparent();
    if (viewparent != null && viewparent instanceof viewgroup)
      ((viewgroup) viewparent).removeview(webview);
    webview.removeallviews();
    webview.destroy();
    webview = null;
  }
  
  @override
  protected void ondestroy() {
    destroywebview(mwebview);
    super.ondestroy();
  }
}

aidl

第一步:创建.aidl文件

  • aidl默认支持以下的类型:
  • java 编程语言中的所有原语类型(如 int、long、char、boolean 等等)
  • string
  • charsequence
  • list
  • map
  • 如果需要导入自己的类型需要加入一个 import 语句(注意:导入的类需要实现parcelabel接口)

aidl文件:

interface iaidlprocess {

  //默认支持原语类型(int、long、char等等)、string、charsequence、list、map
  //自定义类型需要导入 import eebochina.com.testtechniques.testwebview.xxxclass
  //自定义类型传输一定需要是序列化对象
  string getcustomdata();

  void setcustomdata(string str);
}

服务端

public class aidlservice extends service {
  public aidlservice() {
  }
  itestprocess.stub mbinder = new itestprocess.stub() {
    @override
    public string getcustomdata() throws remoteexception {
      return customdata.getinstance().getdata();
    }
  
    @override
    public void setcustomdata(string str) throws remoteexception {
      customdata.getinstance().setdata(str);
    }
  };
  @override
  public ibinder onbind(intent intent) {
    return mbinder;
  }
}

客服端获取绑定接口

  aidlservice maidlservice;
  private serviceconnection serviceconnection = new serviceconnection() {
    @override
    public void onserviceconnected(componentname name, ibinder service) {
      maidlservice = iaidlprocess.stub.asinterface(service);
      mbound = true;
    }
    
    @override
    public void onservicedisconnected(componentname name) {
      mbound = false;
      maidlservice = null;
    }
  };

在获取了绑定接口后就可以直接和服务端通讯了。

2种通讯方式都简单的介绍了下,后面的实际应用还需要根据不同的业务进行调整。

由于aidl是方法直接调用的,从代码扩展和阅读来说比messenger要强很多。

如果有写的不好和不对的地方,希望大家可以及时指出来。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网