【问题标题】:Having problems trying to change architecture to MVVM using Dagger尝试使用 Dagger 将架构更改为 MVVM 时遇到问题
【发布时间】:2019-02-20 16:24:18
【问题描述】:

我目前一直在研究 Android 架构,我正在尝试按照 Google guide 使用 MVVM 构建一个简单的应用程序。我按照教程进行操作,直到进入缓存部分(目前这对我来说并不重要)。问题是我遇到了一些我无法解决的问题。

这是我的片段:

public class OutboundFragment extends Fragment {

    private OutboundFlightsViewModel viewModel;

    public OutboundFragment() {
        // Required empty public constructor
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        viewModel = ViewModelProviders.of(this).get(OutboundFlightsViewModel.class);
        viewModel.init();
        viewModel.getFlights().observe(this, flights -> {
            // Update UI.
        });
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_outbound, container, false);
    }

}

这是我的存储库:

@Singleton
public class FlightsRepository {

    public LiveData<Flights> getFlights() {

        final MutableLiveData<Flights> data = new MutableLiveData<>();

        ApiInterface apiService =
                ApiClient.getClient().create(ApiInterface.class);

        Call<Flights> call = apiService.getFlights();
        call.enqueue(new Callback<Flights>() {
            @Override
            public void onResponse(Call<Flights>call, Response<Flights> response) {
                data.setValue(response.body());
            }

            @Override
            public void onFailure(Call<Flights>call, Throwable t) {
                // Log error here since request failed
            }
        });

        return data;
    }
}

这是我的 ViewModel:

public class OutboundFlightsViewModel extends ViewModel {

    private LiveData<Flights> flights;
    private FlightsRepository flightsRepo;

    @Inject
    public OutboundFlightsViewModel(FlightsRepository flightsRepo) {
        this.flightsRepo = flightsRepo;
    }

    public OutboundFlightsViewModel(){}

    public void init() {
        if (this.flights != null) {
            return;
        }
        if (flightsRepo != null) {
            flights = flightsRepo.getFlights();
        }
    }

    public LiveData<Flights> getFlights() {
        return this.flights;
    }
}

这些是我的 gradle 文件中的依赖项:

    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support:design:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    implementation "android.arch.lifecycle:extensions:1.1.1"
    implementation "android.arch.lifecycle:viewmodel:1.1.1"
    // Dagger
    implementation 'com.google.dagger:dagger:2.20'
    implementation 'com.google.dagger:dagger-android-support:2.20'
    annotationProcessor 'com.google.dagger:dagger-compiler:2.20'
    // Retrofit, gson
    implementation 'com.google.code.gson:gson:2.8.2'
    implementation 'com.squareup.retrofit2:retrofit:2.0.2'
    implementation 'com.squareup.retrofit2:converter-gson:2.0.2'
    // RecyclerView
    implementation 'com.android.support:recyclerview-v7:28.0.0'
    // butter knife
    implementation 'com.jakewharton:butterknife:8.8.1'
    annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'

最后这是包含这两个问题的 logcat:

2019-02-20 13:19:12.864 3864-27637/? E/ExternalAccountType: Unsupported attribute viewStreamItemActivity
2019-02-20 13:19:13.069 1181-1181/? E/LoadedApk: Unable to instantiate appComponentFactory
    java.lang.ClassNotFoundException: Didn't find class "android.support.v4.app.CoreComponentFactory" on path: DexPathList[[],nativeLibraryDirectories=[/system/app/OPBackup/lib/arm64, /system/app/OPBackup/OPBackup.apk!/lib/arm64-v8a, /system/lib64, /system/lib64]]
        at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:169)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
        at android.app.LoadedApk.createAppFactory(LoadedApk.java:226)
        at android.app.LoadedApk.updateApplicationInfo(LoadedApk.java:346)
        at android.app.ActivityThread.handleDispatchPackageBroadcast(ActivityThread.java:5524)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1831)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:193)
        at com.android.server.SystemServer.run(SystemServer.java:482)
        at com.android.server.SystemServer.main(SystemServer.java:322)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:537)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:838)
2019-02-20 13:19:13.092 10596-10622/com.example.mguimaraes.maxmilhas E/libc: Access denied finding property "vendor.debug.egl.profiler"
2019-02-20 13:19:13.093 10596-10622/com.example.mguimaraes.maxmilhas E/libc: Access denied finding property "vendor.debug.prerotation.disable"
2019-02-20 13:19:13.073 1181-1181/? E/LoadedApk: Unable to instantiate appComponentFactory
    java.lang.ClassNotFoundException: Didn't find class "android.support.v4.app.CoreComponentFactory" on path: DexPathList[[],nativeLibraryDirectories=[/system/app/OPBackup/lib/arm64, /system/app/OPBackup/OPBackup.apk!/lib/arm64-v8a, /system/lib64, /system/lib64]]
        at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:169)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
        at android.app.LoadedApk.createAppFactory(LoadedApk.java:226)
        at android.app.LoadedApk.updateApplicationInfo(LoadedApk.java:346)
        at android.app.ActivityThread.handleDispatchPackageBroadcast(ActivityThread.java:5524)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1831)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:193)
        at com.android.server.SystemServer.run(SystemServer.java:482)
        at com.android.server.SystemServer.main(SystemServer.java:322)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:537)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:838)
2019-02-20 13:19:13.149 12490-12516/? E/neplus.launche: Invalid ID 0x00000000.
2019-02-20 13:19:13.153 12490-12516/? E/neplus.launche: Invalid ID 0x00000000.
2019-02-20 13:19:13.172 12490-12516/? E/neplus.launche: Invalid ID 0x00000000.
2019-02-20 13:19:13.172 12490-12516/? E/neplus.launche: Invalid ID 0x00000000.
2019-02-20 13:19:13.184 12490-12516/? E/neplus.launche: Invalid ID 0x00000000.
2019-02-20 13:19:13.184 12490-12516/? E/neplus.launche: Invalid ID 0x00000000.
2019-02-20 13:19:13.192 12490-12516/? E/neplus.launche: Invalid ID 0x00000000.
2019-02-20 13:19:13.192 12490-12516/? E/neplus.launche: Invalid ID 0x00000000.
2019-02-20 13:19:13.192 12490-12516/? E/neplus.launche: Invalid ID 0x00000000.
2019-02-20 13:19:13.197 12490-12516/? E/neplus.launche: Invalid ID 0x00000000.
2019-02-20 13:19:13.198 12490-12516/? E/neplus.launche: Invalid ID 0x00000000.
2019-02-20 13:19:13.198 12490-12516/? E/neplus.launche: Invalid ID 0x00000000.
2019-02-20 13:19:13.201 12490-12516/? E/neplus.launche: Invalid ID 0x00000000.
2019-02-20 13:19:13.343 10596-10596/com.example.mguimaraes.maxmilhas E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.mguimaraes.maxmilhas, PID: 10596
    java.lang.NullPointerException: Attempt to invoke virtual method 'void android.arch.lifecycle.LiveData.observe(android.arch.lifecycle.LifecycleOwner, android.arch.lifecycle.Observer)' on a null object reference
        at com.example.mguimaraes.maxmilhas.Fragments.OutboundFragment.onActivityCreated(OutboundFragment.java:30)
        at android.support.v4.app.Fragment.performActivityCreated(Fragment.java:2460)
        at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1483)
        at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1784)
        at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1852)
        at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:802)
        at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2625)
        at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2411)
        at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2366)
        at android.support.v4.app.FragmentManagerImpl.execSingleAction(FragmentManager.java:2243)
        at android.support.v4.app.BackStackRecord.commitNowAllowingStateLoss(BackStackRecord.java:654)
        at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:146)
        at android.support.v4.view.ViewPager.populate(ViewPager.java:1244)
        at android.support.v4.view.ViewPager.populate(ViewPager.java:1092)
        at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1622)
        at android.view.View.measure(View.java:23355)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6758)
        at android.support.design.widget.CoordinatorLayout.onMeasureChild(CoordinatorLayout.java:733)
        at android.support.design.widget.HeaderScrollingViewBehavior.onMeasureChild(HeaderScrollingViewBehavior.java:95)
        at android.support.design.widget.AppBarLayout$ScrollingViewBehavior.onMeasureChild(AppBarLayout.java:1556)
        at android.support.design.widget.CoordinatorLayout.onMeasure(CoordinatorLayout.java:803)
        at android.view.View.measure(View.java:23355)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6758)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
        at android.support.v7.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:143)
        at android.view.View.measure(View.java:23355)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6758)
        at android.support.v7.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java:401)
        at android.view.View.measure(View.java:23355)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6758)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
        at android.view.View.measure(View.java:23355)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6758)
        at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1535)
        at android.widget.LinearLayout.measureVertical(LinearLayout.java:825)
        at android.widget.LinearLayout.onMeasure(LinearLayout.java:704)
        at android.view.View.measure(View.java:23355)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6758)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
        at com.android.internal.policy.DecorView.onMeasure(DecorView.java:717)
        at android.view.View.measure(View.java:23355)
        at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2917)
        at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1747)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2040)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1635)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7795)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1172)
        at android.view.Choreographer.doCallbacks(Choreographer.java:984)
        at android.view.Choreographer.doFrame(Choreographer.java:809)
2019-02-20 13:19:13.343 10596-10596/com.example.mguimaraes.maxmilhas E/AndroidRuntime:     at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1158)
        at android.os.Handler.handleCallback(Handler.java:873)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6863)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:537)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

我错过了什么吗?我是按照教程一步一步来的。

【问题讨论】:

    标签: java android mvvm dagger-2 dagger


    【解决方案1】:

    首先,为了使用Dagger和ViewModel注入依赖,你需要创建一个ViewModelProvider.Factory的实现:

    @Singleton
    public class ViewModelFactory implements ViewModelProvider.Factory {
        private final Map<Class<? extends ViewModel>, Provider<ViewModel>> creators;
    
        @Inject
        ViewModelFactory(Map<Class<? extends ViewModel>, Provider<ViewModel>> creators) {
            this.creators = creators;
        }
    
        @SuppressWarnings("unchecked")
        @Override
        public <T extends ViewModel> T create(Class<T> modelClass) {
            Provider<? extends ViewModel> creator = creators.get(modelClass);
            if (creator == null) {
                for (Map.Entry<Class<? extends ViewModel>, Provider<ViewModel>> entry : creators.entrySet()) {
                    if (modelClass.isAssignableFrom(entry.getKey())) {
                        creator = entry.getValue();
                        break;
                    }
                }
            }
            if (creator == null) {
                throw new IllegalArgumentException("unknown viewmodel class " + modelClass);
            }
            try {
                return (T) creator.get();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }
    

    此实现将提供ViewModel 子类的实例。

    好吧,现在我们需要配置将提供实例的ViewModelModule。但在此之前,我们需要创建一个注解来标识要提供的ViewModel 的类型:

    @MapKey
    @Documented
    @Target({ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface ViewModelKey {
        Class<? extends ViewModel> value();
    }
    

    @MapKey 是来自 Dagger 的注释,用于标识 @Provides` 方法的返回类型。

    现在,这是我们的ViewModelModule

    @Module
    public interface ViewModelModule {
    
        @Binds
        ViewModelProvider.Factory bindViewModelFactory(ViewModelFactory factory);
    
        @Binds
        @IntoMap
        @ViewModelKey(OutboundFlightsViewModel.class)
        ViewModel bindOutboundFlightsViewModel(OutboundFlightsViewModel viewModel);
    
    }
    

    好的,所以我们需要配置组件:

    @Singleton
    @Component(modules = {
        AndroidSupportInjectionModule.class,
        ViewModelModule.class
        // other modules goes here
    })
    interface AppComponent extends AndroidInjector<App> {
    
        @Component.Builder
        abstract class Builder extends AndroidInjector.Builder<App> {}
    
    }
    

    请注意,有特定的安装模块称为AndroidSupportInjectionModule。该模块是dagger.android 的一部分,其中包含许多类,以使 Dagger for Android 易于使用。

    最后,我们需要初始化从 Dagger 生成的类来创建我们的依赖图:

    public class App extends DaggerApplication {
    
        @Override
        protected AndroidInjector<? extends App> applicationInjector() {
            return DaggerAppComponent.builder().create(this);
        }
    
    }
    

    请注意,App 类扩展了 DaggerApplication 而不是 ApplicationDaggerApplicationdagger.android 包的一部分。

    举个完整的例子,我的 Github 上有一个使用 MVVM + Dagger 2 的项目。

    项目:https://github.com/WellingtonCosta/android-mvvm-databinding

    此外,我还有一个小型库,可以将 Dagger 与 Android 视图模型一起轻松使用。

    项目:https://github.com/WellingtonCosta/viewmodel-dagger

    希望对你有帮助!

    【讨论】:

    • 您好,感谢您的大力帮助!我正在尝试实施您的建议,但我得到“无法解析符号 DaggerAppComponent”。我错过了任何进口吗?
    • 没关系,我重建了项目并解决了问题。我是否必须更改 ViewModel 类或片段上的任何内容?因为我遇到了同样的问题: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.arch.lifecycle.LiveData.observe(android.arch.lifecycle.LifecycleOwner, android.arch.lifecycle.Observer)' on a空对象引用
    【解决方案2】:

    如果您发布一些匕首代码以查看发生了什么,那就太好了。看来您没有很好地注入您的存储库。

    另一方面,您在 ViewModel 初始化中遇到了一些问题。 如果您调试视图模型,您会看到您的 LiveData 始终为空,因为您的 FlightsRepository 无法注入。而你试图在你的片段中观察它而不检查它的状态 --> NullPointerException。

    首先,尽管您有存储库,但您可以初始化 MutableLiveData 变量:

        // View Model snippet
        private MutableLiveData<Flights> flights;
        private FlightsRepository flightsRepo;
    
        @Inject
        public OutboundFlightsViewModel(FlightsRepository flightsRepo) {
            this.flightsRepo = flightsRepo;
        }
    
        public OutboundFlightsViewModel(){}
    
        public void init() {
            flights = new MutableLiveData<Flights>;
    
            if (flightsRepo != null) {
                flights.postValue(flightsRepo.getFlights());
            }
        }
    
        public LiveData<Flights> getFlights() {
            return this.flights;
        }
    

    在这种情况下,您可以在片段中观察到一个空的 LiveData,因此当您修复存储库注入时,只要它有要发布的值,您就可以对这些更改做出反应并做任何您想做的事情。

    关于匕首类:

    你需要你的 ApplicationComponent 来绑定你想提供的每个模块:

    @Singleton
    @Component(modules = [(AndroidInjectionModule::class),  (BuildersModule::class), (RepositoryModule::class)])
    interface ApplicationComponent {
    
        @Component.Builder
        interface Builder {
    
            @BindsInstance
            fun application(application: AppController): Builder
    
            fun build(): ApplicationComponent
        }
    
        fun inject(app: AppController)
    }
    

    您的 BuildersModule 类提供将被注入的每个 Activity。 如果您的 Activity 有需要注入的 Fragment,也需要在此处。

    @Module
    abstract class BuildersModule {
    
        @ContributesAndroidInjector(modules = [(YourViewModelModule::class)])
        internal abstract fun contributeYourActivity(): YourActivity
    }
    

    在此模块中,您将声明要注入的每个存储库。

    @Module
    class RepositoryModule {
        @Provides
        fun yourRepository(): YourRepository {
            return YourRepository()
        }
    }
    

    这是您的视图模型模块,您需要创建视图模型工厂并提供它以便注入。

    @Module
    class YourViewModelModule {
        @Provides
        fun providesYourViewModelFactory(yourRepository: YourRepository): YourViewModelFactory {
            return YourViewModelFactory(yourRepository)
        }
    }
    

    您需要视图模型工厂才能将参数注入您的视图模型类。

    class YourViewModelFactory(private val repository: YourRepository) : ViewModelProvider.Factory {
        override fun <T : ViewModel?> create(modelClass: Class<T>): T {
            if (modelClass.isAssignableFrom(YourViewModel::class.java)) {
                return YourViewModel(repository) as T
            }
    
            throw IllegalArgumentException("unknown view model class")
        }
    }
    

    这是包含您的片段的活动。为了注入您的片段,您需要实现 HasSupportFragmentInjection。

    class OutboundActivity : AppCompatActivity, HasSupportFragmentInjector {
    
       @Inject
       lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Fragment>
    
       override fun supportFragmentInjector(): AndroidInjector<Fragment> {
               return dispatchingAndroidInjector
        }
    
        override fun onCreate(savedInstanceState: Bundle?) {
               super.onCreate(savedInstanceState)
               AndroidInjection.inject(this)
        }
    
    
    }
    

    这里是您的片段,现在它可以接收您注入的视图模型工厂。请注意,现在您的 ViewModelProvider 采用了两个参数,thisviewModelFactory,因此您的视图模型可以接收注入的参数。

    
    class OutboundFragment: Fragment {
    
        @Inject
        lateinit var viewModelFactory: YourViewModelFactory
    
        private var viewModel: OutboundFlightsViewModel
    
        @Override
        public void onActivityCreated(@Nullable Bundle savedInstanceState) {
            super.onActivityCreated(savedInstanceState);
            AndroidSupportInjection.inject(this)
    
            viewModel = ViewModelProviders.of(this, viewModelFactory).get(OutboundFlightsViewModel.class);
            viewModel.init();
            viewModel.getFlights().observe(this, flights -> {
                // Update UI.
            });
        }
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
        }
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            // Inflate the layout for this fragment
            return inflater.inflate(R.layout.fragment_outbound, container, false);
        }
    
    }
    
    

    最后但同样重要的是,您需要在 App 类中重写 onCreate 方法并使用其组件初始化 dagger。注意这里需要实现 HasActivityInjection。

    class AppController : Application(), HasActivityInjector {
    
        @Inject
        lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Activity>
    
    
        override fun onCreate() {
            super.onCreate()
    
            // Registered a global instance of AppController
            appControllerInstance = this
    
            // Init Dagger
            DaggerApplicationComponent.builder()
                    .application(this)
                    .build()
                    .inject(this)
         }
    
          override fun activityInjector(): AndroidInjector<Activity>? {
            return dispatchingAndroidInjector
        }
    }
    
    

    对不起,我每天都用 Kotlin 写这个,我忘记了你是用 Java 编码的。但是不要害怕,它是相似的,你会理解没有问题。 让我知道如果你不能理解某事。

    【讨论】:

    • 您好,感谢您的回复。我对这整个 Dagger 的事情很陌生,所以我认为我只需要使用指南告诉我的内容。但是我尝试了 Wellington 下面建议的解决方案,但我遇到了同样的问题。另外,我尝试使用您添加的代码,但似乎 postValue 具有受保护的访问权限。
    • 为了帮助您使用 Dagger,您应该发布一些模块的代码。是的,postValue 在 LiveData 中具有受保护的访问权限,您应该将类​​型更改为 MutableLiveData。让我编辑 sn-p。
    • 感谢您的回复。关于模块类,我使用的是 Wellington Costa 建议的完全相同的代码。但是 Dagger 并没有生成绑定类,比如“ActivityMainBinding”等。你碰巧知道为什么吗?
    • 我编辑了答案,并添加了一些 Dagger 代码以使您的注射正常工作。对不起语言,我使用 Kotlin 是因为我喜欢它。如果您有任何疑问,请告诉我。继续阅读 Dagger,这是一个庞大的框架,您需要了解它以避免常见错误。
    猜你喜欢
    • 2019-01-25
    • 1970-01-01
    • 2011-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多