`
shuai1234
  • 浏览: 977483 次
  • 性别: Icon_minigender_1
  • 来自: 山西
社区版块
存档分类
最新评论

抢红包插件实现原理浅析

 
阅读更多

抢红包,先看效果图~

抢红包

实现自动抢红包,解决问题有两点:

一:如何实时监听发红包的事件

二:如何在红包到来的时候自动进入页面并自动点击红包

一、如何获取红包到来的事件

为了获取红包到来状态栏的变化,我们要用到一个类:Accessibility

许多Android使用者因为各种情况导致他们要以不同的方式与手机交互。 
这包括了有些用户由于视力上,身体上,年龄上的问题致使他们不能看完整的屏幕或者使用触屏,也包括了无法很好接收到语音信息和提示的听力能力比较弱的用户。 
Android提供了Accessibility功能和服务帮助这些用户更加简单地操作设备,包括文字转语音(这个不支持中文),触觉反馈,手势操作,轨迹球和手柄操作

OK,了解到这一点,那么接下来就顺利点了,首先来看看Accessibility以及AccessibilityService的使用

  1. 新建一个类继承AccessibilityService,并在AndroidManifest文件里注册它:
    <uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" />  
    <application>  
    <service   android:name="com.zkhb.weixinqinghongbao.service.QiangHongBaoService"       
    android:label="@string/app_name"     android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE" >
     <intent-filter>
         <action android:name="android.accessibilityservice.AccessibilityService" />
         </intent-filter>
        <meta-data
          android:name="android.accessibilityservice"          android:resource="@xml/qianghongbao_service_config" />
         </service>
    </application>  
     

在子类QiangHongBaoService里实现几个重要的重载方法:

onServiceConnected() - 可选。系统会在成功连接上你的服务的时候调用这个方法,在这个方法里你可以做一下初始化工作,例如设备的声音震动管理,也可以调用setServiceInfo()进行配置工作。 
onAccessibilityEvent() - 必须。通过这个函数可以接收系统发送来的AccessibilityEvent,接收来的AccessibilityEvent是经过过滤的,过滤是在配置工作时设置的。

onInterrupt() - 必须。这个在系统想要中断AccessibilityService返给的响应时会调用。在整个生命周期里会被调用多次。 
onUnbind() - 可选。在系统将要关闭这个AccessibilityService会被调用。在这个方法中进行一些释放资源的工作。

然后在/res/xml/qianghongbao_service_config.xml:

 

<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"  android:accessibilityEventTypes="typeNotificationStateChanged|typeWindowStateChanged|typeWindowContentChanged"
    android:accessibilityFeedbackType="feedbackGeneric"
    android:accessibilityFlags=""
    android:canRetrieveWindowContent="true"
    android:description="@string/accessibility_description"
    android:notificationTimeout="100"
    android:packageNames="com.tencent.mm" />
 

 

二、主要关注点以及如何在红包到来的时候自动进入页面并自动点击红包

onAccessibilityEvent方法中监听状态栏的变化,主要有:AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED、AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED、AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED

在响应窗体以及窗体内容变化时处理相关逻辑,获取带微信消息时以下代码打开消息:

 

  //将微信的通知栏消息打开
        Notification notification = (Notification) event.getParcelableData();
        PendingIntent pendingIntent = notification.contentIntent;
        try {
            pendingIntent.send();
        } catch (PendingIntent.CanceledException e) {
            e.printStackTrace();
        }
 

 

具体代码网上有很多,一般都是通过:findAccessibilityNodeInfosByTextfindAccessibilityNodeInfosByViewId查找文本或者资源节点进行点击操作,但新版微信开红包页面进行了处理,没有文本信息,而如果采用: 
这里写图片描述 
(上图截取是用的DDMS中的 UI Automator Viewer,如图:Eclipse中:UI Automator Viewer 
或者在sdk的tools目录下:

UI Automator Viewer 
UI Automator Viewer) 
图中resouces-id这种形式就可能出现这种情况:

在了解整个核心后,获取事件不外乎就是通过文本与id判断,那么就可以将文本改为图标方式,将id改为动态id(每次显示都是随机生成),这样一来就可以提高外挂的门槛。

如何进行规避呢,目前我想的是既然开红包的页面文本和ID都有可能会变,那我们能不能找个不变的进行判断呢,考虑过后,我觉得最可能不变的地方就是开红包这个按钮的位置,也就是图中的bounds,于是在思考过后有了下面的处理:

  for (int i = 0; i < nodeInfo.getChildCount(); i++) {
            //Log.e("TAG", "getViewIdResourceName :"+nodeInfo.getChild(i).getViewIdResourceName());
            Rect outBounds = new Rect();
            nodeInfo.getChild(i).getBoundsInScreen(outBounds);
            int left_dp = px2dip(this, 400);
            int top_dp = px2dip(this, 1035);
            int right_dp = px2dip(this, 682);
            int bottom_dp = px2dip(this, 1320);

            int left_px = dip2px(this, left_dp);
            int top_px = dip2px(this, top_dp);
            int right_px = dip2px(this, right_dp);
            int bottom_px = dip2px(this, bottom_dp);

            Rect mStandar = new Rect(left_px,top_px,right_px,bottom_px);
            if(mStandar.contains(outBounds)){
                Log.e("TAG", "outBounds.left :"+outBounds.left+";outBounds.top :"+outBounds.top+";outBounds.right :"+outBounds.right+";outBounds.bottom :"+outBounds.bottom);
                nodeInfo.getChild(i).performAction(AccessibilityNodeInfo.ACTION_CLICK);
                break;
            }
        }

 

这里取的矩形区域要比按钮区域稍大点,然后判断到开红包页面按钮是否在我们预先设置的区域内,如果在,我们直接进行点击开红包操作:AccessibilityNodeInfo.ACTION_CLICK。 
其他比如如何防止重复抢等细节问题,也是要处理的问题。 
好了,直接放下关键代码,仅供参考:

package com.zkhb.weixinqinghongbao.service;

import java.util.Date;
import java.util.List;

import android.accessibilityservice.AccessibilityService;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.KeyguardManager;
import android.app.KeyguardManager.KeyguardLock;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.Rect;
import android.os.Build;
import android.os.Handler;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.Toast;

import com.zkhb.weixinqinghongbao.MainActivity;
import com.zkhb.weixinqinghongbao.R;
import com.zkhb.weixinqinghongbao.entity.HongBaoInfo;
import com.zkhb.weixinqinghongbao.util.DateFormatUtils;
import com.zkhb.weixinqinghongbao.util.LogUtil;

/**
 *
 * 抢红包服务
 */
@SuppressLint("NewApi") 
public class QiangHongBaoService extends AccessibilityService {

//    static final String TAG = "QiangHongBao";

    /** 微信的包名*/
    static final String WECHAT_PACKAGENAME = "com.tencent.mm";
    /** 红包消息的关键字*/
    static final String HONGBAO_TEXT_KEY = "[微信红包]";
    /** 红包消息的关键字*/
    static final String HONGBAO_TEXT_KEY1 = "微信红包";

    private static final int ENVELOPE_RETURN = 0;

    private static final String LOCK_TAG = "屏幕";

    Handler handler = new Handler();
    /** 是否在抢红包界面里*/
//    public boolean isInMM=false;
    /** 是否可以点击*/
//    public boolean ISCLICKED=false;
    /** 是否进入过拆红包界面*/
    public static boolean ISCOMINQIANGCHB=false;
    //真正的
    public static boolean ISCOMINQIANGCHB2=false;
    //真正的判断
    public static boolean ISCOMINQIANGCHB3=false;
     /** 是否来自通知栏*/
    private static boolean ISCOMNOTIFY=false;

    private PowerManager pm;
    //点亮屏幕
    private WakeLock mWakeLock;
     //解锁锁定屏幕
    private KeyguardLock keyguardLock;
    /**判断之前用户是否锁屏  */
    private static boolean islock=false;
    /**通知服务 */
    private NotificationManager n_manager;
    public void unlock(){
        if(pm==null){
            pm = (PowerManager) getApplication().getSystemService(Context.POWER_SERVICE);
        }
        boolean isScreenOn = pm.isScreenOn();//如果为true,则表示屏幕“亮”了,否则屏幕“暗”了。
        if(!isScreenOn){
            islock=true;
            KeyguardManager keyguardManager = (KeyguardManager)getSystemService(KEYGUARD_SERVICE);
            keyguardLock = keyguardManager.newKeyguardLock(LOCK_TAG);
            keyguardLock.disableKeyguard();

            mWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, LOCK_TAG);  
            mWakeLock.acquire();
        }
    }

    public void lock(){
        if(islock){
            //释放屏幕常亮锁
            if(null != mWakeLock) {
                mWakeLock.release();
            }
            //屏幕锁定
            if(keyguardLock!=null){
                keyguardLock.reenableKeyguard();
            }
        }
    }
    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        final int eventType = event.getEventType();

        LogUtil.info("事件---->" + event);

        //通知栏事件
        if(eventType == AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED) {
            unlock();
            List<CharSequence> texts = event.getText();
            if(!texts.isEmpty()) {
                for(CharSequence t : texts) {
                    String text = String.valueOf(t);
                    if(text.contains(HONGBAO_TEXT_KEY)) {
                        ISCOMNOTIFY=true;
                        ISCOMINQIANGCHB=false;
                        openNotify(event);
                        break;
                    }
                }
            }
        } else if(eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
            unlock();
            openHongBao(event);
//            AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
//            List<AccessibilityNodeInfo> findAccessibilityNodeInfosByText = nodeInfo.findAccessibilityNodeInfosByText("领取红包");
//            if(findAccessibilityNodeInfosByText.isEmpty()){
//              isInMM=false;
//            }else{
//              isInMM=true;
//            }
//            List<CharSequence> text = event.getText();
//            if(text.size()>=0){
//              CharSequence charSequence = text.get(0);
////                if(charSequence.equals("微信")){
////                    isInMM=true;
////                }else{
////                    isInMM=false;
////                }
//            }
        }else if(eventType==AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED && ISCOMNOTIFY){
            unlock();
            openHongBao(event);
            List<AccessibilityNodeInfo> InfoText = getRootInActiveWindow().findAccessibilityNodeInfosByText("领取红包");
            if(!InfoText.isEmpty()){
                checkKey2();
                ISCOMNOTIFY=false;
            }
        }
    }
    /*@Override
    protected boolean onKeyEvent(KeyEvent event) {
        //return super.onKeyEvent(event);
        return true;
    }*/
    @Override
    public boolean onUnbind(Intent intent) {
        Toast.makeText(this, "断开抢红包服务", Toast.LENGTH_SHORT).show();
        ISCOMINQIANGCHB=false;
        islock=false;
        ISCOMINQIANGCHB2=false;
        ISCOMINQIANGCHB3=false;
        ISCOMNOTIFY=false;
        setNotification("已关闭抢红包小助手服务~~",Notification.FLAG_AUTO_CANCEL,"已关闭抢红包小助手服务~~~");
        return super.onUnbind(intent);
    }
    @Override
    public void onInterrupt() {
        Toast.makeText(this, "中断抢红包服务", Toast.LENGTH_SHORT).show();
    }

    @Override
    protected void onServiceConnected() {
        super.onServiceConnected();
        ISCOMINQIANGCHB=false;
        ISCOMINQIANGCHB2=false;
        ISCOMINQIANGCHB3=false;
        islock=false;
        ISCOMNOTIFY=false;

        setNotification("已开启抢红包小助手服务~~",Notification.FLAG_NO_CLEAR,"已开启抢红包小助手服务~~~");

        Toast.makeText(this, "连接抢红包服务", Toast.LENGTH_SHORT).show();
    }

    private void setNotification(String content,int flags,String title) {
        if(n_manager==null){
            n_manager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
        }
        n_manager.cancelAll();
        Notification notification=new Notification(R.drawable.ic_launcher, content, System.currentTimeMillis());
//        notification.defaults |= Notification.DEFAULT_VIBRATE;
//        long[] vibrate = {0,100,200,300}; //0毫秒后开始振动,振动100毫秒后停止,再过200毫秒后再次振动300毫秒
//        notification.vibrate=vibrate;
        notification.flags |= flags; //表明在点击了通知栏中的"清除通知"后,此通知不清除,

        Intent notificationIntent = new Intent(this,MainActivity.class); //点击该通知后要跳转的Activity
        PendingIntent contentIntent = PendingIntent.getActivity(getApplicationContext(),0,notificationIntent,0);
        notification.setLatestEventInfo(getApplicationContext(), title, "进入微信抢红包~~", contentIntent);

        n_manager.notify(0, notification);
    }

    private void sendNotifyEvent(){
        AccessibilityManager manager= (AccessibilityManager)getSystemService(ACCESSIBILITY_SERVICE);
        if (!manager.isEnabled()) {
            return;
        }
        AccessibilityEvent event=AccessibilityEvent.obtain(AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED);
        event.setPackageName(WECHAT_PACKAGENAME);
        event.setClassName(Notification.class.getName());
        CharSequence tickerText = HONGBAO_TEXT_KEY;
        event.getText().add(tickerText);
        manager.sendAccessibilityEvent(event);
    }

    /** 打开通知栏消息*/
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
    private void openNotify(AccessibilityEvent event) {
        if(event.getParcelableData() == null || !(event.getParcelableData() instanceof Notification)) {
            return;
        }
        //将微信的通知栏消息打开
        Notification notification = (Notification) event.getParcelableData();
        PendingIntent pendingIntent = notification.contentIntent;
        try {
            pendingIntent.send();
        } catch (PendingIntent.CanceledException e) {
            e.printStackTrace();
        }
    }

    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
    private void openHongBao(AccessibilityEvent event) {
        if("com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyReceiveUI".equals(event.getClassName())) {
            //点中了红包,下一步就是去拆红包
            ISCOMINQIANGCHB=true;
            ISCOMINQIANGCHB2=true;
            checkKey1();
        } else if("com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyDetailUI".equals(event.getClassName())) {
            //拆完红包后看详细的纪录界面
             LogUtil.info("事件---->com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyDetailUI");
             //nonething
//          if(ISCOMINQIANGCHB){
//              ISCOMINQIANGCHB=false;
//          }
             if(ISCOMINQIANGCHB2){
                 ISCOMINQIANGCHB3=true;
             }else{
                 ISCOMINQIANGCHB3=false;
             }
            checkKey3();
            ISCOMINQIANGCHB=true;
            ISCOMINQIANGCHB2=false;
            performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);
            if(getSharedPreferences("config", Context.MODE_PRIVATE).getBoolean("auto", false)){
                performGlobalAction(AccessibilityService.GLOBAL_ACTION_HOME);
            }
            lock();
        } else if("com.tencent.mm.ui.LauncherUI".equals(event.getClassName())) {
//          isInMM=true;
            //在聊天界面,去点中红包
            LogUtil.info("事件---->com.tencent.mm.ui.LauncherUI");
            checkKey2();
        }
    }
    @SuppressLint("NewApi") @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
    private void checkKey3() {
        AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
         if(nodeInfo == null) {
             LogUtil.info("rootWindow为空333");
             return;
         }
         //TODO
         List<AccessibilityNodeInfo> findAccessibilityNodeInfosByText = nodeInfo.findAccessibilityNodeInfosByText("元");
         if(findAccessibilityNodeInfosByText.size()>=0){
             AccessibilityNodeInfo accessibilityNodeInfo2 = findAccessibilityNodeInfosByText.get(0).getParent();
             CharSequence money = accessibilityNodeInfo2.getChild(2).getText();
             CharSequence name = accessibilityNodeInfo2.getChild(0).getText();
             if(ISCOMINQIANGCHB3){
                 HongBaoInfo info=new HongBaoInfo();
                 info.setStrDateTime(DateFormatUtils.format("yyyy-MM-dd HH:mm:ss", new Date()));
                 info.setStrMoney(money+"");
                 info.setStrName(name+"");
                 info.save();
             }
             Toast.makeText(getApplicationContext(), money+":::"+name, 0).show();
         }
//       List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewId = nodeInfo.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/aw8");
//       AccessibilityNodeInfo accessibilityNodeInfo = findAccessibilityNodeInfosByViewId.get(0);
//       CharSequence text = accessibilityNodeInfo.getText(); 
    }

    private void checkKey1() {
        AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
        if(nodeInfo == null) {
            LogUtil.info("rootWindow为空11111");
            return;
        }

        for (int i = 0; i < nodeInfo.getChildCount(); i++) {
            Log.e("TAG", "getViewIdResourceName :"+nodeInfo.getChild(i).getViewIdResourceName());
            Rect outBounds = new Rect();
            nodeInfo.getChild(i).getBoundsInScreen(outBounds);
            int left_dp = px2dip(this, 400);
            int top_dp = px2dip(this, 1035);
            int right_dp = px2dip(this, 682);
            int bottom_dp = px2dip(this, 1320);

            int left_px = dip2px(this, left_dp);
            int top_px = dip2px(this, top_dp);
            int right_px = dip2px(this, right_dp);
            int bottom_px = dip2px(this, bottom_dp);

            Rect mStandar = new Rect(left_px,top_px,right_px,bottom_px);
            if(mStandar.contains(outBounds)){
                Log.e("TAG", "outBounds.left :"+outBounds.left+";outBounds.top :"+outBounds.top+";outBounds.right :"+outBounds.right+";outBounds.bottom :"+outBounds.bottom);
                nodeInfo.getChild(i).performAction(AccessibilityNodeInfo.ACTION_CLICK);
                break;
            }
//          nodeInfo.performAction(action)//[405,1042][675,1312]
        }
        //List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByText("拆红包");

//  List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/b5d");
//        for(AccessibilityNodeInfo n : list) {
//            n.performAction(AccessibilityNodeInfo.ACTION_CLICK);
//        }
    }

    private void checkKey2() {
        AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
        if(nodeInfo == null) {
            LogUtil.info("rootWindow为空222222");
            return;
        }
        List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByText("领取红包");
        if(list.isEmpty()) {
            list = nodeInfo.findAccessibilityNodeInfosByText(HONGBAO_TEXT_KEY);
            for(AccessibilityNodeInfo n : list) {
                LogUtil.info("-->微信红包:" + n);
                n.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                break;
            }
        } else {
            //最新的红包领起
            AccessibilityNodeInfo parent = list.get(list.size() - 1).getParent();
//          Log.w(TAG, "ISCLICKED::"+ISCLICKED)!ISCLICKED;
            if(parent != null && !ISCOMINQIANGCHB) {
                parent.performAction(AccessibilityNodeInfo.ACTION_CLICK);
            }
//            for(int i = list.size() - 1; i >= 0; i --) {
//                AccessibilityNodeInfo parent = list.get(i).getParent();
//                Log.i(TAG, "-->领取红包:" + parent);
//                if(parent != null && parent.isClickable()) {
//                    parent.performAction(AccessibilityNodeInfo.ACTION_CLICK);
//                    break;
//                }
//            }
//            performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);
        }
    }
    /**
     * @param info 当前节点
     * @param matchFlag 需要匹配的文字
     * @param type  操作的类型
     */
    @SuppressLint("NewApi") 
    public void recycle(AccessibilityNodeInfo info, String matchFlag, int type) {
        if (info != null) {
            if (info.getChildCount() == 0) {
                CharSequence desrc = info.getContentDescription();
                switch (type) {
                    case ENVELOPE_RETURN://返回
                        if (desrc != null && matchFlag.equals(info.getContentDescription().toString().trim())) {
                            if (info.isCheckable()) {
                                info.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                            } else {
                                performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);
                            }
                        }
                        break;
                }
            } else {
                int size = info.getChildCount();
                for (int i = 0; i < size; i++) {
                    AccessibilityNodeInfo childInfo = info.getChild(i);
                    if (childInfo != null) {
                        LogUtil.info("index: " + i + " info" + childInfo.getClassName() + " : " + childInfo.getContentDescription()+" : "+info.getText());
                        recycle(childInfo, matchFlag, type);
                    }
                }
            }
        }
    }
    @Override
    public void onDestroy() {
        super.onDestroy();
        lock();
    }
    /** 
     * 根据手机的分辨率从 dip 的单位 转成为 px(像素) 
     */  
    public static int dip2px(Context context, float dpValue) {  
        final float scale = context.getResources().getDisplayMetrics().density;  
        return (int) (dpValue * scale + 0.5f);  
    }  

    /** 
     * 根据手机的分辨率从 px(像素) 的单位 转成为 dp 
     */  
    public static int px2dip(Context context, float pxValue) {  
//        final float scale = context.getResources().getDisplayMetrics().density;  
        return (int) (pxValue / 3 + 0.5f);  //3是本人手机的设备密度
    }  
}

 

 

AccessibilityService还可以用在智能安装、虚拟按键上都有很多应用,这样的实践只是给我们一种解决问题另外的一种思路,问题嘛,总还是要解决的。

分享到:
评论
4 楼 zkzqzzz 2016-07-13  
感谢博主  原来那些类都不是必须的   或者自己写!!博主真棒!!!会一直关注博主的最新动态
3 楼 zkzqzzz 2016-07-13  
博主   请问你的其他类在哪里呢?
2 楼 zkzqzzz 2016-07-12  
其他类在哪呢?
1 楼 zkzqzzz 2016-07-12  
很喜欢博主的一句话,“问题嘛,总还是要解决的” 

相关推荐

    Android抢红包插件实现原理浅析

    《Android抢红包插件实现原理浅析》 在如今的社交时代,抢红包已经成为了一种流行的游戏,尤其在微信、QQ等社交应用中。本文将深入解析如何利用Android的无障碍服务(Accessibility Service)来实现自动抢红包的...

    Android微信抢红包功能的实现原理浅析

    在Android平台上,微信抢红包功能的实现主要依赖于Android系统的辅助服务 AccessibilityService。这个服务允许应用程序监听并响应用户与系统交互的各种事件,如焦点变化、窗口状态改变等,从而实现自动化操作,例如...

    vue实现原理浅析

    那么本文是以一种通俗易懂的的角度来实现一个简单 的双向数据绑定系统,如果你用过vue却对vue的实现原理不太清楚,或者没用过vue想学习vue那我相信看完本文你会的vue的实现有一个比较简单明确的了解。

    Java 读写锁实现原理浅析

    "Java 读写锁实现原理浅析" Java 读写锁实现原理浅析是 Java 并发编程中一个非常重要的主题。在多线程编程中,读写锁是解决读写并发问题的常用机制。本文主要介绍了 Java 读写锁实现原理浅析,包括读写锁的定义、...

    Weex工作原理浅析

    阿里Weex框架(iOS版本)原理分析 阿里Weex框架(iOS版本)原理分析 阿里Weex框架(iOS版本)原理分析

    java 虚拟机原理浅析

    java 虚拟机原理浅析,希望大家来交流

    移动通信原理浅析.pptx

    移动通信原理浅析.pptx

    hadoop原理浅析及安装.doc

    hadoop原理浅析及安装.doc

    MySQL JOIN 工作原理浅析1

    "MySQL JOIN 工作原理浅析" MySQL JOIN 工作原理浅析是数据库管理系统中的一种关键技术,用于将多个表连接起来以获取所需数据。本文将对 MySQL 中的 JOIN 工作原理进行浅析,包括 Nested Loop Join 和 Hash Join ...

    浅析JQuery框架及其插件应用

    ### 浅析JQuery框架及其插件应用 #### 一、jQuery框架概述 JQuery,一个由美国程序员John Resig创建的JavaScript库,自诞生以来迅速成为全球开发者钟爱的工具之一。它以“写得少,做得多”(WRITELESS,DOMORE)的...

    MRP插件浅析.pptx

    《MRP插件浅析》一文深入探讨了在手机游戏开发中,如何利用MRP插件提升游戏性能与功能多样性。本文将基于标题、描述、标签及部分内容,全面解析MRP插件的工作机制、运行原理及开发要点,旨在为游戏开发者提供一份...

    ZAO背后的深度学习算法原理浅析 深度学习原理.pdf

    深度学习算法原理浅析 本文对ZAO背后的深度学习算法原理进行了浅析,介绍了ZAO是基于deep fake算法演变出来的一种产品,提供了deepFake lab的下载地址,计算机硬件的要求等等。文章从更底层的算法角度出发,带大家...

    用微观经济学原理浅析生活中的现象.pdf

    用微观经济学原理浅析生活中的现象.pdf

    Struts1工作原理浅析.doc

    Struts1工作原理浅析 1.引入struts1 2.struts1工作原理 3.struts1工作机制 4.struts1的安装于基本配置 5.ActionServlet

    浅析Android手机的应用双开实现原理及风险.pdf

    浅析Android手机的应用双开实现原理及风险 一、应用双开的实现原理 应用双开是指在同一个Android手机上运行多个相同的应用程序,这种技术使得用户可以在同一个手机上拥有多个独立的应用空间,从而满足不同场景下的...

    代码生成原理浅析PPT

    本文档是无垠式代码生成器研发阶段的理论探讨过程,对理解无垠式代码生成器源码和和平之翼代码生成器这两种动词算子式代码生成器是很重要的。

    Photoshop通道原理浅析

    解析PS通道原理,让你更深入的了解通道原理

    室内定位原理浅析

    室内定位是垂直专业方向,除了需要信号处理相关专业知识,还需要对机器学习有一个很深入的了解。因此,真正要做好,需要很长时间的技术积累和经验总结。百度一直秉持让大家平等获取信息的理念,持续投入资源,支持该...

    ChatGPT原理分析,ChatGPT原理浅析,ChatGPT原理

    ChatGPT核心是基于RNN、LSTM、Attention、Transformer模型演进发展而来的,通过自监督学习(SSL, Self Supervised Learning)预训练、监督学习优调(Fine Tuning)、强化学习实现非监督学习训练的自然语言处理的大语言...

    浅析构建电话银行原理

    基于PC串口电话机浅析构建电话银行原理设计

Global site tag (gtag.js) - Google Analytics