轻量级社会化分享openShare源码解析

开篇

关于社会化分享,一般用友盟比较多,但是也有其他的实现方式,这里介绍一下
openShare ,可以不利用官方SDK,直接进行分享。和友盟相比包小了太多,不过貌似没法统计,各有特色吧。

正文

openShare整体结构.png

如上图openShare的整体结构主要分为两大部分,openShare 和各大平台的分类。每个平台都去扩展OpenShare的类方法,来很好的保证平台的增加和整体功能的完善等。
我们通过新浪微博和QQ的登录和分享来介绍openShare的使用以及对源码的实现方法的理解。

新浪微博分享

AppDelegate配置

首先导入头文件并注册相关的key

 //第一步:注册key
    [OpenShare connectQQWithAppId:@"1103194207"];
    [OpenShare connectWeiboWithAppKey:@"402180334"];
    [OpenShare connectWeixinWithAppId:@"wxd930ea5d5a258f4f"];
    [OpenShare connectRenrenWithAppId:@"228525" AndAppKey:@"1dd8cba4215d4d4ab96a49d3058c1d7f"];
    [OpenShare connectAlipay];//支付宝参数都是服务器端生成的,这里不需要key.

然后设置分享的回调方法代码如下,这里等下分析OpenShare+Weibo文件的时候详细再说。

-(BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{
    //第二步:添加回调
    if ([OpenShare handleOpenURL:url]) {
        return YES;
    }
    //这里可以写上其他OpenShare不支持的客户端的回调,比如支付宝等。
    return YES;
}

ViewController中的调用

在示例代码中登录和分享的调用方法如下:

   UIView *ret=[[UIView alloc] initWithFrame:frame];
    UIButton *auth=[self button:@"登录" WithCenter:CGPointMake(frame.size.width/2, 40)];
    [ret addSubview:auth];
    [auth addEventHandler:^(id sender) {
        [OpenShare WeiboAuth:@"all" redirectURI:@"http://openshare.gfzj.us/" Success:^(NSDictionary *message) {
            ULog(@"微博登录成功:\n%@",message);
        } Fail:^(NSDictionary *message, NSError *error) {
            ULog(@"微博登录失败:\n%@\n%@",message,error);
        }];
    } forControlEvents:UIControlEventTouchUpInside];

   UIButton *textShare=[self button:@"分享纯文本" WithCenter:CGPointMake(auth.center.x, calcYFrom(auth)+40)];
    [ret addSubview:textShare];
    textShare.tag=1001;
    [textShare addTarget:self action:@selector(weiboViewHandler:) forControlEvents:UIControlEventTouchUpInside];
    
    UIButton *imgShare=[self button:@"分享图片" WithCenter:CGPointMake(auth.center.x, calcYFrom(textShare)+40)];
    [ret addSubview:imgShare];
    imgShare.tag=1002;
    [imgShare addTarget:self action:@selector(weiboViewHandler:) forControlEvents:UIControlEventTouchUpInside];
    
    UIButton *newsShare=[self button:@"分享新闻" WithCenter:CGPointMake(auth.center.x, calcYFrom(imgShare)+40)];
    [ret addSubview:newsShare];
    newsShare.tag=1003;
    [newsShare addTarget:self action:@selector(weiboViewHandler:) forControlEvents:UIControlEventTouchUpInside];

//微博分享的实现方法
-(void)weiboViewHandler:(UIButton*)btn{
    OSMessage *message=[[OSMessage alloc]init];
    message.title=@"hello openshare (message.title)";
    if (btn.tag>=1002) {
        message.image=testImage;
    }
    if (btn.tag==1003) {
        message.link=@"http://openshare.gfzj.us/";
    }
    [OpenShare shareToWeibo:message Success:^(OSMessage *message) {
        ULog(@"分享到sina微博成功:\%@",message);
    } Fail:^(OSMessage *message, NSError *error) {
        ULog(@"分享到sina微博失败:\%@\n%@",message,error);
    }];
}

这里首先先说一下登录的事件添加方式

   [auth addEventHandler:^(id sender) {
        [OpenShare WeiboAuth:@"all" redirectURI:@"http://openshare.gfzj.us/" Success:^(NSDictionary *message) {
            ULog(@"微博登录成功:\n%@",message);
        } Fail:^(NSDictionary *message, NSError *error) {
            ULog(@"微博登录失败:\n%@\n%@",message,error);
        }];
    } forControlEvents:UIControlEventTouchUpInside];

方法的添加是由下图中的UIControl+Blocks文件中实现的


UIControl+Blocks

在.h中创建了- (void)addEventHandler:(ActionBlock)handler forControlEvents:(UIControlEvents)controlEvents;
以及ActionBlock。我们点进.m,可以看到主要由两个方法组成代码如下:

- (void)addEventHandler:(ActionBlock)handler forControlEvents:(UIControlEvents)controlEvents
{
    objc_setAssociatedObject(self, &UIButtonHandlerKey, handler, OBJC_ASSOCIATION_COPY_NONATOMIC);
    [self addTarget:self action:@selector(callActionHandler:) forControlEvents:controlEvents];

};
}
- (void)callActionHandler:(id)sender
{
    ActionBlock handler = (ActionBlock)objc_getAssociatedObject(self, &UIButtonHandlerKey);
    if (handler) {
        handler(sender);
    }
}

首先

  objc_setAssociatedObject(self, &UIButtonHandlerKey, handler, OBJC_ASSOCIATION_COPY_NONATOMIC);

为runtime的动态属性的添加,各个参数对应的解释如下

      * @param self  需要添加关联的对象
     *  @param UIButtonHandlerKey     添加的唯一标识符
     *  @param handler   关联的对象
     *  @param OBJC_ASSOCIATION_COPY_NONATOMIC  关联的策略,是个枚举

这句话可以理解为,以OBJC_ASSOCIATION_COPY_NONATOMIC的关联策略为自己添加一个标识符为UIButtonHandlerKey的handler对象。
点进这句话我们可以看到系统对应的关联策略的枚举,有以下几种形式

    typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) {
     OBJC_ASSOCIATION_ASSIGN = 0,           //< Specifies a weak reference to the associated object.
    OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, //< Specifies a strong reference to the associated object.
                                               The association is not made atomically.
    OBJC_ASSOCIATION_COPY_NONATOMIC = 3,   //< Specifies that the associated object is copied.
                                              The association is not made atomically.
    OBJC_ASSOCIATION_RETAIN = 01401,       //< Specifies a strong reference to the associated object.
                                              The association is made atomically.
    OBJC_ASSOCIATION_COPY = 01403          //< Specifies that the associated object is copied.
                                              The association is made atomically.
};

OK,接下来在看对应的添加的callActionHandler事件中的代码

ActionBlock handler = (ActionBlock)objc_getAssociatedObject(self, &UIButtonHandlerKey);
  if (handler) {//判断block是否为null 防止crash
        handler(sender);
    }

ActionBlock通过标示符UIButtonHandlerKey,得到的之前的管理属性,然后判断如果block不为空,进行下一步的操作。

OpenShare+Weibo

我们从调用处着手开始分析一下源码中的一些方法。登录和分享,最先调起的两个方法分别为:
登录

+(void)WeiboAuth:(NSString*)scope redirectURI:(NSString*)redirectURI Success:(authSuccess)success Fail:(authFail)fail;

分享调起方法

+(void)shareToWeibo:(OSMessage*)msg Success:(shareSuccess)success Fail:(shareFail)fail;

点击这两个方法我们首先进入到的是OpenShare+Weibo,一个专门用来处理微博的分类中,我们可以看到一共有以下4个方法:

+(void)connectWeiboWithAppKey:(NSString *)appKey;
+(BOOL)isWeiboInstalled;
/**
 *  分享到微博,微博只支持三种类型:文本/图片/链接。根据OSMessage自动判定想分享的类型。
 *
 *  @param msg     要分享的msg
 *  @param success 分享成功回调
 *  @param fail    分享失败回调
 */
+(void)shareToWeibo:(OSMessage*)msg Success:(shareSuccess)success Fail:(shareFail)fail;

/**
 *  微博登录OAuth
 *
 *  @param scope       scope,如果不填写,默认是all
 *  @param redirectURI 必须填写,可以通过http://open.weibo.com/apps/402180334/info/advanced编辑(后台不验证,但是必须填写一致)
 *  @param success     登录成功回调
 *  @param fail        登录失败回调
 */
+(void)WeiboAuth:(NSString*)scope redirectURI:(NSString*)redirectURI Success:(authSuccess)success Fail:(authFail)fail;

分别用来注册微博相关的key,判断是否安装以及主要的分享登录。
平台和key的设置

每个分类中设置不同的schema,区分平台
+(void)connectWeiboWithAppKey:(NSString *)appKey{
    [self set:schema Keys:@{@"appKey":appKey}];
}
调用openShare的设置方法
+(void)set:(NSString*)platform Keys:(NSDictionary *)key{
    if (!keys) {
        keys=[[NSMutableDictionary alloc] init];
    }
    keys[platform]=key;
}
  • 分享的方法
    下面通过分享方法,介绍一下核心的分享的实现方式
+(void)shareToWeibo:(OSMessage*)msg Success:(shareSuccess)success Fail:(shareFail)fail{
    if (![self beginShare:schema Message:msg Success:success Fail:fail]) {
        return;
    }
    NSDictionary *message;
    //根据不同的分享形式 设置不同的字典格式 
    if ([msg isEmpty:@[@"link" ,@"image"] AndNotEmpty:@[@"title"] ]) {
        //text类型分享
        message= @{
                   @"__class" : @"WBMessageObject",
                   @"text" :msg.title
                   };
    }else if ([msg isEmpty:@[@"link" ] AndNotEmpty:@[@"title",@"image"] ]) {
        //图片类型分享
        message=@{
                  @"__class" : @"WBMessageObject",
                  @"imageObject":@{
                          @"imageData":[self dataWithImage:msg.image]
                          },
                  @"text" : msg.title
                  };
        
    }else if ([msg isEmpty:nil AndNotEmpty:@[@"title",@"link" ,@"image"] ]) {
        //链接类型分享
        message=@{
                  @"__class" : @"WBMessageObject",
                  @"mediaObject":@{
                          @"__class" : @"WBWebpageObject",
                          @"description": msg.desc?:msg.title,
                          @"objectID" : @"identifier1",
                          @"thumbnailData":msg.thumbnail ? [self dataWithImage:msg.thumbnail] : [self dataWithImage:msg.image  scale:CGSizeMake(100, 100)],    //三目运算
                          @"title": msg.title,
                          @"webpageUrl":msg.link
                          }
                  
                  };
    }
    NSString *uuid=[[NSUUID UUID] UUIDString];
    NSArray *messageData=@[
                           @{@"transferObject":[NSKeyedArchiver archivedDataWithRootObject:@{
                                                                                             @"__class" :@"WBSendMessageToWeiboRequest",
                                                                                             @"message":message,
                                                                                             @"requestID" :uuid,
                                                                                             }]},
                           @{@"userInfo":[NSKeyedArchiver archivedDataWithRootObject:@{}]},
                           
                           @{@"app":[NSKeyedArchiver archivedDataWithRootObject:@{ @"appKey" : [self keyFor:schema][@"appKey"],@"bundleID" : [self CFBundleIdentifier]}]}
                           ];
    [UIPasteboard generalPasteboard].items=messageData;
    [self openURL:[NSString stringWithFormat:@"weibosdk://request?id=%@&sdkversion=003013000",uuid]];
}

通过代码我们可以看到主要步骤为:判断参数是否存在-->设置分享方式 -->设置messageData并归档信息-->把数据放到粘贴板上 -->打开网址( [[UIApplication sharedApplication] openURL:[NSURL URLWithString:url]];
的方式)
下面我们分析是如何设置分享方式的,代码如下:

if ([msg isEmpty:@[@"link" ,@"image"] AndNotEmpty:@[@"title"] ]) {
        //text类型分享
        message= @{
                   @"__class" : @"WBMessageObject",
                   @"text" :msg.title
                   };
    }

msg代表的OSMessage对象包含内容如下:

@interface OSMessage : NSObject
@property NSString* title;
@property NSString* desc;
@property NSString* link;
@property UIImage *image;
@property UIImage *thumbnail;
@property OSMultimediaType multimediaType;
//for 微信
@property NSString* extInfo;
@property NSString* mediaDataUrl;
@property NSString* fileExt;
@property (nonatomic, strong) NSData *file;   /// 微信分享gif/文件
/**
 *  判断emptyValueForKeys的value都是空的,notEmptyValueForKeys的value都不是空的。
 *
 *  @param emptyValueForKeys    空值的key
 *  @param notEmptyValueForKeys 非空值的key
 *
 *  @return YES/NO
 */
-(BOOL)isEmpty:(NSArray*)emptyValueForKeys AndNotEmpty:(NSArray*)notEmptyValueForKeys;
@end

OSMessage是用来保存分享的数据信息的对象。可以通过其中包含的内容来进行区分分享的内容类型。而其中:-(BOOL)isEmpty:(NSArray)emptyValueForKeys AndNotEmpty:(NSArray)notEmptyValueForKeys;介绍如下:

-(BOOL)isEmpty:(NSArray*)emptyValueForKeys AndNotEmpty:(NSArray*)notEmptyValueForKeys{
    @try {
        if (emptyValueForKeys) {
            for (NSString *key in emptyValueForKeys) {
                if ([self valueForKeyPath:key]) {//valueForKeyPath 可以获取OSMessage中相同key的元素
                             return NO;   
 }
        }
        if (notEmptyValueForKeys) {
            for (NSString *key in notEmptyValueForKeys) {
                if (![self valueForKey:key]) {//取OSMessage对象里 key对应的内容 如果不存在返回NO
                    return NO;
                }
            }
        }
        return YES;
    }
    @catch (NSException *exception) {
        NSLog(@"isEmpty error:\n %@",exception);
        return NO;
    }
}

方法实现的目的是 判断emptyValueForKeys的value都是空的,notEmptyValueForKeys的value都不是空的。valueForKeyPath判断给定的数组中的内容是否有OSMessage中相同key的元素,如果有的话返回NO,走下一种分享模式。valueForKey判断给定的内容是否也存在于OSMessage的对象中,如果存在返回YES。
对下面代码中的翻译为:

 if ([msg isEmpty:@[@"link" ,@"image"] AndNotEmpty:@[@"title"] ]) {
        //text类型分享
        message= @{
                   @"__class" : @"WBMessageObject",
                   @"text" :msg.title
                   };
    }

如果OSMessage对象中不包含,link,image,只包含title,则设置的分享格式是纯文本分享,同时设置分享的字典格式。

    [UIPasteboard generalPasteboard].items=messageData;

在新浪微博的分享中以上述方式,把要分享的内容放至剪贴板上。

  • 回调方法

接下来看回调函数

+(BOOL)Weibo_handleOpenURL{
}

主要代码如下:

    if ([url.scheme hasPrefix:@"wb"]) {
        NSArray *items=[UIPasteboard generalPasteboard].items;
        NSMutableDictionary *ret=[NSMutableDictionary dictionaryWithCapacity:items.count];
        for (NSDictionary *item in items) {
            for (NSString *k in item) {
                ret[k]=[k isEqualToString:@"transferObject"]?[NSKeyedUnarchiver unarchiveObjectWithData:item[k]]:item[k];
            }
        }
        NSDictionary *transferObject=ret[@"transferObject"];
        if ([transferObject[@"__class"] isEqualToString:@"WBAuthorizeResponse"]) {//通过反归档 取出的类名  登录
            //auth
            if ([transferObject[@"statusCode"] intValue]==0) {
                if ([self authSuccessCallback]) {
                    [self authSuccessCallback](transferObject);
                }
            }else{
                if ([self authFailCallback]) {
                    NSError *err=[NSError errorWithDomain:@"weibo_auth_response" code:[transferObject[@"statusCode"] intValue] userInfo:transferObject];
                    [self authFailCallback](transferObject,err);
                }
            }
        }else if ([transferObject[@"__class"] isEqualToString:@"WBSendMessageToWeiboResponse"]) {//分享
            //分享回调
            if ([transferObject[@"statusCode"] intValue]==0) {
                if ([self shareSuccessCallback]) {
                    [self shareSuccessCallback]([self message]);
                }
            }else{
                if ([self shareFailCallback]) {
                    NSError *err=[NSError errorWithDomain:@"weibo_share_response" code:[transferObject[@"statusCode"] intValue] userInfo:transferObject];
                    [self shareFailCallback]([self message],err);
                }
            }
        }
        return YES;
    }

主要逻辑为:取出剪贴板上内容 -->根据遍历循环取出-->根据之前设置的字典格式区分内容-->设置回调信息

一次分享的整体流程
  • 01:对应平台设置key 和相关平台设置
+(void)set:(NSString*)platform Keys:(NSDictionary *)key
  • 02:对应平台取值方法
+(NSDictionary *)keyFor:(NSString*)platform{
    return [keys valueForKey:platform]?keys[platform]:nil;
}
  • 03:创建创建要分享的OSMessage对象
 OSMessage *message=[[OSMessage alloc]init];
  • 04:调去分享微博的方法

  • 05:分享方法的调起内部实现

+(void)shareToWeibo:(OSMessage*)msg Success:(shareSuccess)success Fail:(shareFail)fail
  • 06:区分分享方式,设置分享的字典格式,内容以items的形式复制至剪贴板
 [UIPasteboard generalPasteboard].items=messageData;
  • 07:拼接uuid 打开软件
  [self openURL:[NSString stringWithFormat:@"weibosdk://request?id=%@&sdkversion=003013000",uuid]];
  • 08 走OpenShare中回调的hook方法确定是否有回调
+(BOOL)handleOpenURL:(NSURL*)openUrl{
}
  • 09分享结束回调,取出剪贴板的数据,做回调处理
实现原理
  • A程序通过Uri跳转到对应的分享程序B里。
  • 在B里面,他读取从粘贴板里的数据和根据uri做对应的分享处理。
  • 分享完,B把分享的状态结果也放到粘贴板里。然后,根据A之前设好的uri,又跳回到A应用中。
  • 然后A把粘贴板的数据读出来,就知道分享是成功还是失败了。
hook方法
+(BOOL)handleOpenURL:(NSURL*)openUrl{
    returnedURL=openUrl;
    for (NSString *key in keys) {
        SEL sel=NSSelectorFromString([key stringByAppendingString:@"_handleOpenURL"]);
        if ([self respondsToSelector:sel]) {
            NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:
                                        [self methodSignatureForSelector:sel]];
            [invocation setSelector:sel];  
            
            [invocation setTarget:self];
            [invocation invoke];  
            BOOL returnValue;
            [invocation getReturnValue:&returnValue];
            if (returnValue) {
                return YES;
            }
        }else{
            NSLog(@"fatal error: %@ is should have a method: %@",key,[key stringByAppendingString:@"_handleOpenURL"]);
        }
    }
    return NO;
}

我们主要看一下下面这个方法中的内容

+(BOOL)handleOpenURL:(NSURL*)openUrl{  }

创建了一个SEL对象,来获取之前分类中不同的handleOpenURL方法,通过NSSelectorFromString 来判断 未实现的方法是不是我们想要动态添加的方法如:

+(BOOL)Weibo_handleOpenURL{}

如果实现了,利用NSInvocation来直接调用这个消息,在设置万签名,和设置对象之后,执行[invocation invoke],然后根据Weibo_handleOpenURL方法中的返回内容通过getReturnValue来确定有无回调方法。

  • NSInvocation介绍
    NSInvocation对象只能使用其类方法来初始化,不可使用alloc/init方法。它执行调用之前,需要设置两个方法:setSelector: 和setArgument:atIndex,简单的NSInvocation使用方法如下:
  SEL   selector = @selector(Test2);

    methodSign = [[self class] instanceMethodSignatureForSelector:selector];
    
    NSInvocation *mehtod2Invocation = [NSInvocation invocationWithMethodSignature:methodSign];
    
    [mehtod2Invocation setSelector:selector];
    
    [mehtod2Invocation invokeWithTarget:self];
    
    BOOL returnValue = 1;
    
    [mehtod2Invocation getReturnValue:&returnValue];
    
    NSLog(@"返回值:%ld",returnValue);



-(BOOL)Test2{
    
    return NO;
}

有返回值无参数类型的函数,此处的打印数值应该是0,因为Test2的返回值是NO。

   //有返回值,有参数
    
    SEL  selector = @selector(Test3:);
    
    NSMethodSignature *method3Sign = [[self class] instanceMethodSignatureForSelector:selector];
    
    NSInvocation *method3Invocation = [NSInvocation invocationWithMethodSignature:method3Sign];
    
    [method3Invocation setTarget: self];
    
    [method3Invocation setSelector:selector];
    
    NSString *arg1 = @"testArg1";
    
    [method3Invocation setArgument:&arg1 atIndex:2];
    
    [method3Invocation invoke];
    
//    [method3Invocation setReturnValue:&arg1];
    [method3Invocation getReturnValue:&arg1];

    NSLog(@".....%@",arg1);


-(NSString *)Test3 :(NSString*)a{
    
    a= @"122334";
    
    NSLog(@"----%@",a);
    
    return a;
}

如果是 [method3Invocation getReturnValue:&arg1] 他的作用是获取函数的返回结果,打印结果为

2017-06-22 16:14:40.850 01234567899[2884:103358] ----122334
2017-06-22 16:14:40.850 01234567899[2884:103358] .....122334

如果是 [method3Invocation setReturnValue:&arg1] 他的作用是设置函数的返回结果 函数表达式变为如下:

-(NSString *)Test3 :(NSString*)a{
    NSLog(@"----%@",a);
    return a;
}

打印结果为

2017-06-22 16:17:28.261 01234567899[2924:105348] ----testArg1
2017-06-22 16:17:28.261 01234567899[2924:105348] .....testArg1

[invocation invoke]; 这个方法中,只要调用invocation的invoke方法,就代表需要执行NSInvocation对象中制定对象的指定方法,并且传递指定的参数。
至此我们基本说完了新浪微博分享的整体流程那么我们在大致说一下QQ分享的时候,与新浪微博的区别。

QQ分享的区别

调用分享的主要函数举例如下:

+(void)shareToQQFriends:(OSMessage*)msg Success:(shareSuccess)success Fail:(shareFail)fail{
    if ([self beginShare:schema Message:msg Success:success Fail:fail]) {
        [self openURL:[self genShareUrl:msg to:0]];
    }
}

主要的区别在genShareUrl中

+(NSString*)genShareUrl:(OSMessage*)msg to:(int)shareTo{ }

数据的归档并放置到剪贴板的方法为[[UIPasteboard generalPasteboard] setData:data forPasteboardType:key];不同于新浪微博的 [UIPasteboard generalPasteboard].items=messageData;具体实现如下:

/**
 数据的归档 并放置剪贴板
 */
+(void)setGeneralPasteboard:(NSString*)key Value:(NSDictionary*)value encoding:(OSPboardEncoding)encoding{
    if (value&&key) {
        NSData *data=nil;
        NSError *err;
        switch (encoding) {
            case OSPboardEncodingKeyedArchiver://归档方式存储
                data=[NSKeyedArchiver archivedDataWithRootObject:value];
                break;
            case OSPboardEncodingPropertyListSerialization://序列化
                data=[NSPropertyListSerialization dataWithPropertyList:value format:NSPropertyListBinaryFormat_v1_0 options:0 error:&err];
            default:
                NSLog(@"encoding not implemented");
                break;
        }
        if (err) {
            NSLog(@"error when NSPropertyListSerialization: %@",err);
        }else if (data){
            [[UIPasteboard generalPasteboard] setData:data forPasteboardType:key];///*data类型的数据放在粘贴板中,pasteboardType  类型 字符串*/
        }
    }
}

/**
 从剪贴板取出数据  并解档
 */
+(NSDictionary*)generalPasteboardData:(NSString*)key encoding:(OSPboardEncoding)encoding{
    NSData *data=[[UIPasteboard generalPasteboard] dataForPasteboardType:key];//从剪贴板取出数据
    NSDictionary *dic=nil;
    if (data) {
        NSError *err;
        switch (encoding) {
            case OSPboardEncodingKeyedArchiver:
                dic= [NSKeyedUnarchiver unarchiveObjectWithData:data];
                break;
            case OSPboardEncodingPropertyListSerialization:
                dic=[NSPropertyListSerialization propertyListWithData:data options:0 format:0 error:&err];
            default:
                break;
        }
        if (err) {
            NSLog(@"error when NSPropertyListSerialization: %@",err);
        }
    }
    return dic;
}

并在打开软件的过程中使用了base64编码等,其余的原理大致相同。
到这里,对openShare实现的过程和源码有了大致的说明,可以开心的使用啦。

00

后记

这篇介绍,主要是自己对openShare,实现的一种认识,以及对源码的理解,可能存在一定的错误和理解偏差,希望积极指出。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,204评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,091评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,548评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,657评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,689评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,554评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,302评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,216评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,661评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,851评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,977评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,697评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,306评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,898评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,019评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,138评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,927评论 2 355

推荐阅读更多精彩内容