当前位置: 首页 > 工具软件 > 凡信 > 使用案例 >

Android应用源码仿微信凡信聊天项目源码

洪开济
2023-12-01

本Demo是一个基于安卓的仿微信项目源码、IM通信部分是基于环信的SDK开发的、对于个人开发者或者小企业来说、做IM用第三方的也是一种趋势吧、毕竟自己整一套可供运营使用的IM系统几乎是不切实际的(技术门槛和维护成本)、之前用环信做了几个外包项目、其中有些设计和安排我觉得很赞。

文件:url80.ctfile.com/f/25127180-734963047-848c15?p=551685 (访问密码: 551685)

所以总结了以前的经验和收获、做了这套全仿微信的APP、总的来说、这里面大的架构还是沿用了环信官方提供的UIdemo、但是里面的很多的细节和大部分页面都是我精心按照微信的逻辑和UI设计进行编写的、功能上目前解决了好友体系、用户资料、单聊、群聊等社交功能、后续还会继续更新类似于更换聊天背景、搜索本地用户、朋友圈、更多聊天表情等功能。


依赖注入以及使用:

// 注册容器
var sc goioc.IServiceCollection = &ServiceCollection{}
// 注入服务
goioc.AddServiceOf[IAnimal, Dog](sc, goioc.Scope)
// 构建提供器
p := sc.Build()
// 获取服务
obj := goioc.GetIAnimal
接口介绍
IServiceCollection 是一个容器接口,通过此接口,将需要进行依赖注入的对象注册到容器中。

IServiceProvider 是一个服务提供器,当服务注册到容器后,构建一个服务提供器,IServiceProvider 可以管理服务的生命周期以及提供服务。

IDispose 接口用于声明此对象在 IServiceProvider 结束时,需要执行接口释放对象。

// IDispose 释放接口
type IDispose interface {
// Dispose 释放资源
Dispose()
}
除此之外,goioc 中还定义了部分扩展函数,如泛型注入等,代码量不多,简单易用。

使用 goioc
如何使用
注入的服务有两种形式,第一种是 B:A,即 B 实现了 A,使用的时候获取 A ;第二种是注入 B,使用的时候获取 B。

// 第一种
AddServiceOfA,B
// 第二种
AddServiceB
A 可以是接口或结构体,只要 B 实现了 A 即可。

定义一个接口:

type IAnimal interface {
Println(s string)
}
实现这个接口:

type Dog struct {
Id int
}

func (my Dog) Println(s string) {
fmt.Println(s)
}

当使用依赖注入框架时,我们可以将接口和实现分开,甚至放到两个模块中,可以随时替换接口的实现。

注册服务和获取服务的代码示例如下:

func Demo() {
sc := &ServiceCollection{}
goioc.AddServiceOf[IAnimal, Dog](sc, goioc.Scope)
p := sc.Build()
animal := goioc.GetIIAnimal
animal.Println(“test”)
}
下面讲解编码过程。

首先创建 IServiceCollection 容器,容器中可以注册服务。

sc := &ServiceCollection{}
然后通过接口注入服务:

goioc.AddServiceOf[IAnimal, Dog](sc, goioc.Scope)
这个函数是泛型方法。如果不使用泛型,则注入过程麻烦得多。

注册完毕后,开始构建提供器:

p := sc.Build()
然后获取服务:

animal := goioc.GetI[IAnimal](p)
animal.Println("test")

生命周期
goioc 中定义了三个生命周期:

const (
Transient ServiceLifetime = iota
Scope
Singleton
)
Transient:瞬时模式,每次获取到的都是新的对象;

Scope:作用域模式,同一个 Provider 中获取到的是同一个对象。

Singleton:单例模式,同一个 ServiceCollection 获取到的是同一个对象,也就是所有 Provider 获取到的都是同一个对象。

如果是单例模式(Singleton),那么无论多少次 Build,对象始终是同一个:

在注册服务的时候,需要注明对象生命周期。

goioc.AddServiceOf[IAnimal, Dog](sc, goioc.Scope)
生命周期为 scope 的注入,同一个 Provider 中,获取到的对象是一样的。

sc := &ServiceCollection{}
goioc.AddServiceOf[IAnimal, Dog](sc, goioc.Scope)
p := sc.Build()

// 第一次获取对象
animal1 := goioc.GetI[IAnimal](p)
if animal1 == nil {
	t.Errorf("service is nil!")
}
animal1.Println("test")

// 第二次获取对象
animal2 := goioc.GetI[IAnimal](p)
if animal2 == nil {
	t.Errorf("service is nil!")
}

// animal1 和 animal2 引用了同一个对象
if animal1 != animal2 {
	t.Errorf("animal1 != animal2")
}

实例一,Scope 生命周期的对象,在同一个提供器下获取到的都是同一个对象。

sc := &ServiceCollection{}
goioc.AddServiceHandlerOf[IAnimal, Dog](sc, goioc.Scope, func(provider goioc.IServiceProvider) interface{} {
	return &Dog{
		Id: 3,
	}
})

p := sc.Build()

// 第一次获取
a := goioc.GetI[IAnimal](p)

if v := a.(*Dog); v == nil {
	t.Errorf("service is nil!")
}
v := a.(*Dog)
if v.Id != 2 {
	t.Errorf("Life cycle error")
}
v.Id = 3

// 第二次获取
aa := goioc.GetI[IAnimal](p)
v = aa.(*Dog)
if v.Id != 3 {
	t.Errorf("Life cycle error")
}

// 重新构建的 scope,不是同一个对象
pp := sc.Build()
aaa := goioc.GetI[IAnimal](pp)
v = aaa.(*Dog)
if v.Id != 2 {
	t.Errorf("Life cycle error")
}

实例二, ServiceCollection 构建的提供器,单例模式下获取到的都是同一个对象。

sc := &ServiceCollection{}
goioc.AddServiceHandler[Dog](sc, goioc.Singleton, func(provider goioc.IServiceProvider) interface{} {
	return &Dog{
		Id: 2,
	}
})

p := sc.Build()
b := goioc.GetS[Dog](p)
if b.Id != 2 {
	t.Errorf("Life cycle error")
}

b.Id = 3

bb := goioc.GetS[Dog](p)
if b.Id != bb.Id {
	t.Errorf("Life cycle error")
}
ppp := sc.Build()

bbb := goioc.GetS[Dog](ppp)
if b.Id != bbb.Id {
	t.Errorf("Life cycle error")
}

实例化
由开发者决定如何实例化一个对象。

主要由注册形式决定,有四个泛型函数实现注册服务:

// AddService 注册对象
func AddService[T any](con IServiceCollection, lifetime ServiceLifetime)

// AddServiceHandler 注册对象,并自定义如何初始化实例
func AddServiceHandler[T any](con IServiceCollection, lifetime ServiceLifetime, f func(provider IServiceProvider) interface{})

// AddServiceOf 注册对象,注册接口或父类型及其实现,serviceType 必须实现了 baseType
func AddServiceOf[I any, T any](con IServiceCollection, lifetime ServiceLifetime)

// AddServiceHandlerOf 注册对象,注册接口或父类型及其实现,serviceType 必须实现了 baseType,并自定义如何初始化实例
func AddServiceHandlerOf[I any, T any](con IServiceCollection, lifetime ServiceLifetime, f func(provider IServiceProvider) interface{})
AddService[T any]:只注册可被实例化的对象:

AddService[T any]
goioc.AddService[Dog](sc, goioc.Scope)
AddServiceHandler 注册一个接口或结构体,自定义实例化。

func(provider goioc.IServiceProvider) interface{} 函数会在实例化对象时执行。

goioc.AddServiceHandler[Dog](sc, goioc.Scope, func(provider goioc.IServiceProvider) interface{} {
	return &Dog{
		Id: 1,
	}
})

在实例化时,如果这个对象还依赖其他服务,则可以通过 goioc.IServiceProvider 来获取其他依赖。

例如下面示例中,一个依赖另一个对象,可以自定义实例化函数,从容器中取出其他依赖对象,然后构建一个新的对象。

goioc.AddServiceHandler[Dog](sc, goioc.Scope, func(provider goioc.IServiceProvider) interface{} {
	a := goioc.GetI[IA](provider)
	return &Dog{
		Id: 1,
        A:	a,
	}
})
goioc.AddServiceHandler[Dog](sc, goioc.Scope, func(provider goioc.IServiceProvider) interface{} {
	config := goioc.GetI[Config](provider)
	if config.Enable == false
	return &Dog{
		Id: 1,
	}
})
 类似资料: