Constructs a InvocationTargetException with a target exception

本文详细阐述了在使用Blazeds与后台Java交互时,访问FlexSession中值时遇到TargetException的问题。文章指出,问题源于在写入和取出session值时使用了看似相同的类实则为不同类的情况。通过深入分析,作者分享了如何避免此类错误的方法,以及在实际开发中如何提高代码质量与细心的重要性。
Constructs a InvocationTargetException with a target exception
flex通过blazeds与后台java交互,访问flexSession里的值时,总是报上面那个错误。
让人抓狂,在网上搜,有朋友说在数据库交互时遇到过,这与我的问题相差太远。
在万般无奈时,发现写入session值时与取值时,两个类名虽相同,实际上是两个不同
的类,哎,当细心,再细心,再细心哪
/* * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ @file:RestrictTo(RestrictTo.Scope.LIBRARY) package androidx.lifecycle import android.annotation.SuppressLint import android.app.Application import android.os.Bundle import androidx.annotation.RestrictTo import androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory.Companion.getInstance import androidx.lifecycle.ViewModelProvider.NewInstanceFactory.Companion.instance import androidx.lifecycle.viewmodel.CreationExtras import androidx.savedstate.SavedStateRegistry import androidx.savedstate.SavedStateRegistryOwner import java.lang.reflect.Constructor import java.lang.reflect.InvocationTargetException /** * [androidx.lifecycle.ViewModelProvider.Factory] that can create ViewModels accessing and * contributing to a saved state via [SavedStateHandle] received in a constructor. * If `defaultArgs` bundle was passed into the constructor, it will provide default * values in `SavedStateHandle`. * * If ViewModel is instance of [androidx.lifecycle.AndroidViewModel], it looks for a * constructor that receives an [Application] and [SavedStateHandle] (in this order), * otherwise it looks for a constructor that receives [SavedStateHandle] only. * [androidx.lifecycle.AndroidViewModel] is only supported if you pass a non-null * [Application] instance. */ class SavedStateViewModelFactory : ViewModelProvider.OnRequeryFactory, ViewModelProvider.Factory { private var application: Application? = null private val factory: ViewModelProvider.Factory private var defaultArgs: Bundle? = null private var lifecycle: Lifecycle? = null private var savedStateRegistry: SavedStateRegistry? = null /** * Constructs this factory. * * When a factory is constructed this way, a component for which [SavedStateHandle] is * scoped must have called [enableSavedStateHandles]. * @see [createSavedStateHandle] docs for more details. */ constructor() { factory = ViewModelProvider.AndroidViewModelFactory() } /** * Creates [SavedStateViewModelFactory]. * * [androidx.lifecycle.ViewModel] created with this factory can access to saved state * scoped to the given `activity`. * * @param application an application. If null, [AndroidViewModel] instances will not be * supported. * @param owner [SavedStateRegistryOwner] that will provide restored state for created * [ViewModels][androidx.lifecycle.ViewModel] */ constructor( application: Application?, owner: SavedStateRegistryOwner ) : this(application, owner, null) /** * Creates [SavedStateViewModelFactory]. * * [androidx.lifecycle.ViewModel] created with this factory can access to saved state * scoped to the given `activity`. * * When a factory is constructed this way, if you add any [CreationExtras] those arguments will * be used instead of the state passed in here. It is not possible to mix the arguments * received here with the [CreationExtras]. * * @param application an application. If null, [AndroidViewModel] instances will not be * supported. * @param owner [SavedStateRegistryOwner] that will provide restored state for created * [ViewModels][androidx.lifecycle.ViewModel] * @param defaultArgs values from this `Bundle` will be used as defaults by [SavedStateHandle] * if there is no previously saved state or previously saved state misses a value by such key. */ @SuppressLint("LambdaLast") constructor(application: Application?, owner: SavedStateRegistryOwner, defaultArgs: Bundle?) { savedStateRegistry = owner.savedStateRegistry lifecycle = owner.lifecycle this.defaultArgs = defaultArgs this.application = application factory = if (application != null) getInstance(application) else ViewModelProvider.AndroidViewModelFactory() } /** * {@inheritDoc} * * @throws IllegalStateException if the provided extras do not provide a * [ViewModelProvider.NewInstanceFactory.VIEW_MODEL_KEY] */ override fun <T : ViewModel> create(modelClass: Class<T>, extras: CreationExtras): T { val key = extras[ViewModelProvider.NewInstanceFactory.VIEW_MODEL_KEY] ?: throw IllegalStateException( "VIEW_MODEL_KEY must always be provided by ViewModelProvider" ) return if (extras[SAVED_STATE_REGISTRY_OWNER_KEY] != null && extras[VIEW_MODEL_STORE_OWNER_KEY] != null) { val application = extras[ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY] val isAndroidViewModel = AndroidViewModel::class.java.isAssignableFrom(modelClass) val constructor: Constructor<T>? = if (isAndroidViewModel && application != null) { findMatchingConstructor(modelClass, ANDROID_VIEWMODEL_SIGNATURE) } else { findMatchingConstructor(modelClass, VIEWMODEL_SIGNATURE) } // doesn't need SavedStateHandle if (constructor == null) { return factory.create(modelClass, extras) } val viewModel = if (isAndroidViewModel && application != null) { newInstance(modelClass, constructor, application, extras.createSavedStateHandle()) } else { newInstance(modelClass, constructor, extras.createSavedStateHandle()) } viewModel } else { val viewModel = if (lifecycle != null) { create(key, modelClass) } else { throw IllegalStateException("SAVED_STATE_REGISTRY_OWNER_KEY and" + "VIEW_MODEL_STORE_OWNER_KEY must be provided in the creation extras to" + "successfully create a ViewModel.") } viewModel } } /** * Creates a new instance of the given `Class`. * * @param key a key associated with the requested ViewModel * @param modelClass a `Class` whose instance is requested * @return a newly created ViewModel * * @throws UnsupportedOperationException if the there is no lifecycle */ fun <T : ViewModel> create(key: String, modelClass: Class<T>): T { // empty constructor was called. val lifecycle = lifecycle ?: throw UnsupportedOperationException( "SavedStateViewModelFactory constructed with empty constructor supports only " + "calls to create(modelClass: Class<T>, extras: CreationExtras)." ) val isAndroidViewModel = AndroidViewModel::class.java.isAssignableFrom(modelClass) val constructor: Constructor<T>? = if (isAndroidViewModel && application != null) { findMatchingConstructor(modelClass, ANDROID_VIEWMODEL_SIGNATURE) } else { findMatchingConstructor(modelClass, VIEWMODEL_SIGNATURE) } // doesn't need SavedStateHandle constructor ?: // If you are using a stateful constructor and no application is available, we // use an instance factory instead. return if (application != null) factory.create(modelClass) else instance.create(modelClass) val controller = LegacySavedStateHandleController.create( savedStateRegistry!!, lifecycle, key, defaultArgs ) val viewModel: T = if (isAndroidViewModel && application != null) { newInstance(modelClass, constructor, application!!, controller.handle) } else { newInstance(modelClass, constructor, controller.handle) } viewModel.setTagIfAbsent( AbstractSavedStateViewModelFactory.TAG_SAVED_STATE_HANDLE_CONTROLLER, controller ) return viewModel } /** * {@inheritDoc} * * @throws IllegalArgumentException if the given modelClass does not have a classname */ override fun <T : ViewModel> create(modelClass: Class<T>): T { // ViewModelProvider calls correct create that support same modelClass with different keys // If a developer manually calls this method, there is no "key" in picture, so factory // simply uses classname internally as as key. val canonicalName = modelClass.canonicalName ?: throw IllegalArgumentException("Local and anonymous classes can not be ViewModels") return create(canonicalName, modelClass) } /** * @hide */ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) override fun onRequery(viewModel: ViewModel) { // needed only for legacy path if (lifecycle != null) { LegacySavedStateHandleController.attachHandleIfNeeded( viewModel, savedStateRegistry!!, lifecycle!! ) } } } internal fun <T : ViewModel?> newInstance( modelClass: Class<T>, constructor: Constructor<T>, vararg params: Any ): T { return try { constructor.newInstance(*params) } catch (e: IllegalAccessException) { throw RuntimeException("Failed to access $modelClass", e) } catch (e: InstantiationException) { throw RuntimeException("A $modelClass cannot be instantiated.", e) } catch (e: InvocationTargetException) { throw RuntimeException( "An exception happened in constructor of $modelClass", e.cause ) } } private val ANDROID_VIEWMODEL_SIGNATURE = listOf<Class<*>>( Application::class.java, SavedStateHandle::class.java ) private val VIEWMODEL_SIGNATURE = listOf<Class<*>>(SavedStateHandle::class.java) // it is done instead of getConstructor(), because getConstructor() throws an exception // if there is no such constructor, which is expensive internal fun <T> findMatchingConstructor( modelClass: Class<T>, signature: List<Class<*>> ): Constructor<T>? { for (constructor in modelClass.constructors) { val parameterTypes = constructor.parameterTypes.toList() if (signature == parameterTypes) { @Suppress("UNCHECKED_CAST") return constructor as Constructor<T> } if (signature.size == parameterTypes.size && parameterTypes.containsAll(signature)) { throw UnsupportedOperationException( "Class ${modelClass.simpleName} must have parameters in the proper " + "order: $signature" ) } } return null } 帮我分析这部分代码
09-24
详解下面这个工厂方法 package com.tplink.tpm5.component.core; import android.app.Activity; import android.app.Application; import android.os.Bundle; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentActivity; import androidx.lifecycle.AbstractSavedStateViewModelFactory; import androidx.lifecycle.AndroidViewModel; import androidx.lifecycle.SavedStateHandle; import androidx.lifecycle.ViewModel; import androidx.lifecycle.ViewModelProvider; import androidx.savedstate.SavedStateRegistryOwner; import com.tplink.libtpnetwork.mesh.context.MeshNetworkContext; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.Arrays; /** * Created by yujingzhi@tp-link.com.cn on 2019/6/27. */ public class MeshViewModelFactory extends AbstractSavedStateViewModelFactory { protected final Application mApplication; private final MeshNetworkContext mMeshNetworkContext; public MeshViewModelFactory(Fragment fragment) { this(fragment, null); } public MeshViewModelFactory(FragmentActivity activity) { this(activity, null); } public MeshViewModelFactory(Fragment fragment, MeshNetworkContext meshNetworkContext) { this(checkApplication(checkActivity(fragment)), meshNetworkContext, fragment, fragment.getArguments()); } public MeshViewModelFactory(FragmentActivity activity, MeshNetworkContext meshNetworkContext) { this(checkApplication(activity), meshNetworkContext, activity, activity.getIntent() == null ? null : activity.getIntent().getExtras()); } /** * Constructs this factory. * * @param owner {@link SavedStateRegistryOwner} that will provide restored state for created * {@link ViewModel ViewModels} * @param defaultArgs values from this {@code Bundle} will be used as defaults by * {@link SavedStateHandle} passed in {@link ViewModel ViewModels} * if there is no previously saved state */ public MeshViewModelFactory(Application application, MeshNetworkContext meshNetworkContext, @NonNull SavedStateRegistryOwner owner, @Nullable Bundle defaultArgs) { super(owner, defaultArgs); mApplication = application; mMeshNetworkContext = meshNetworkContext; } @NonNull @Override protected <T extends ViewModel> T create(@NonNull String key, @NonNull Class<T> modelClass, @NonNull SavedStateHandle handle) { boolean isAndroidViewModel = AndroidViewModel.class.isAssignableFrom(modelClass); Constructor<T> constructor; Class<?>[] constructorSignature; if (isAndroidViewModel && mApplication != null) { constructorSignature = MESH_ANDROID_VIEW_MODEL_SIGNATURE; constructor = findMatchingConstructor(modelClass, MESH_ANDROID_VIEW_MODEL_SIGNATURE); if (constructor == null) { constructorSignature = ANDROID_VIEW_MODEL_SIGNATURE; constructor = findMatchingConstructor(modelClass, ANDROID_VIEW_MODEL_SIGNATURE); } } else { constructorSignature = MESH_VIEW_MODEL_SIGNATURE; constructor = findMatchingConstructor(modelClass, MESH_VIEW_MODEL_SIGNATURE); if (constructor == null) { constructorSignature = VIEW_MODEL_SIGNATURE; constructor = findMatchingConstructor(modelClass, VIEW_MODEL_SIGNATURE); } } // doesn't need SavedStateHandle if (constructor == null) { if (mApplication != null) { return ViewModelProvider.AndroidViewModelFactory.getInstance(mApplication).create(modelClass); } else { try { return modelClass.newInstance(); } catch (InstantiationException | IllegalAccessException e) { throw new RuntimeException("Cannot create an instance of " + modelClass, e); } } } try { T viewModel; if (isAndroidViewModel && mApplication != null) { if (constructorSignature == MESH_ANDROID_VIEW_MODEL_SIGNATURE) { viewModel = constructor.newInstance(mApplication, handle, mMeshNetworkContext); } else { viewModel = constructor.newInstance(mApplication, handle); } } else { if (constructorSignature == MESH_VIEW_MODEL_SIGNATURE) { viewModel = constructor.newInstance(handle, mMeshNetworkContext); } else { viewModel = constructor.newInstance(handle); } } return viewModel; } catch (IllegalAccessException e) { throw new RuntimeException("Failed to access " + modelClass, e); } catch (InstantiationException e) { throw new RuntimeException("A " + modelClass + " cannot be instantiated.", e); } catch (InvocationTargetException e) { throw new RuntimeException("An exception happened in constructor of " + modelClass, e.getCause()); } } public MeshNetworkContext getMeshNetworkContext() { return mMeshNetworkContext; } private static Application checkApplication(Activity activity) { Application application = activity.getApplication(); if (application == null) { throw new IllegalStateException("Your activity/fragment is not yet attached to " + "Application. You can't request ViewModel before onCreate call."); } return application; } private static Activity checkActivity(Fragment fragment) { Activity activity = fragment.getActivity(); if (activity == null) { throw new IllegalStateException("Can't create ViewModelProvider for detached fragment"); } return activity; } private static final Class<?>[] MESH_ANDROID_VIEW_MODEL_SIGNATURE = new Class[]{Application.class, SavedStateHandle.class, MeshNetworkContext.class}; private static final Class<?>[] ANDROID_VIEW_MODEL_SIGNATURE = new Class[]{Application.class, SavedStateHandle.class}; private static final Class<?>[] MESH_VIEW_MODEL_SIGNATURE = new Class[]{SavedStateHandle.class, MeshNetworkContext.class}; private static final Class<?>[] VIEW_MODEL_SIGNATURE = new Class[]{SavedStateHandle.class}; @SuppressWarnings("unchecked") private static <T> Constructor<T> findMatchingConstructor(Class<T> modelClass, Class<?>[] signature) { for (Constructor<?> constructor : modelClass.getConstructors()) { Class<?>[] parameterTypes = constructor.getParameterTypes(); if (Arrays.equals(signature, parameterTypes)) { return (Constructor<T>) constructor; } } return null; } }
11-04
这一个factory是如何创建viewmodel的 public class AccountViewModelFactory extends AbstractSavedStateViewModelFactory { protected final Application mApplication; public AccountViewModelFactory(Fragment fragment) { this(checkApplication(checkActivity(fragment)), fragment, fragment.getArguments()); } public AccountViewModelFactory(FragmentActivity activity) { this(checkApplication(activity), activity, activity.getIntent() == null ? null : activity.getIntent().getExtras()); } /** * Constructs this factory. * * @param owner {@link SavedStateRegistryOwner} that will provide restored state for created * {@link ViewModel ViewModels} * @param defaultArgs values from this {@code Bundle} will be used as defaults by * {@link SavedStateHandle} passed in {@link ViewModel ViewModels} * if there is no previously saved state */ public AccountViewModelFactory(Application application, @NonNull SavedStateRegistryOwner owner, @Nullable Bundle defaultArgs) { super(owner, defaultArgs); mApplication = application; } @NonNull @Override protected <T extends ViewModel> T create(@NonNull String key, @NonNull Class<T> modelClass, @NonNull SavedStateHandle handle) { boolean isAndroidViewModel = AndroidViewModel.class.isAssignableFrom(modelClass); Constructor<T> constructor; Class<?>[] constructorSignature; if (isAndroidViewModel && mApplication != null) { constructorSignature = ACCOUNT_ANDROID_VIEW_MODEL_SIGNATURE; constructor = findMatchingConstructor(modelClass, ACCOUNT_ANDROID_VIEW_MODEL_SIGNATURE); if (constructor == null) { constructorSignature = ANDROID_VIEW_MODEL_SIGNATURE; constructor = findMatchingConstructor(modelClass, ANDROID_VIEW_MODEL_SIGNATURE); } } else { constructorSignature = ACCOUNT_VIEW_MODEL_SIGNATURE; constructor = findMatchingConstructor(modelClass, ACCOUNT_VIEW_MODEL_SIGNATURE); if (constructor == null) { constructorSignature = VIEW_MODEL_SIGNATURE; constructor = findMatchingConstructor(modelClass, VIEW_MODEL_SIGNATURE); } } // doesn't need SavedStateHandle if (constructor == null) { if (mApplication != null) { return ViewModelProvider.AndroidViewModelFactory.getInstance(mApplication).create(modelClass); } else { try { return modelClass.newInstance(); } catch (InstantiationException | IllegalAccessException e) { throw new RuntimeException("Cannot create an instance of " + modelClass, e); } } } try { T viewModel; TCAccountContext accountContext = AppCloudNetworkService.requireCurrentAccountContext(); if (isAndroidViewModel && mApplication != null) { if (constructorSignature == ACCOUNT_ANDROID_VIEW_MODEL_SIGNATURE) { viewModel = constructor.newInstance(mApplication, handle, accountContext); } else { viewModel = constructor.newInstance(mApplication, handle); } } else { if (constructorSignature == ACCOUNT_VIEW_MODEL_SIGNATURE) { viewModel = constructor.newInstance(handle, accountContext); } else { viewModel = constructor.newInstance(handle); } } return viewModel; } catch (IllegalAccessException e) { throw new RuntimeException("Failed to access " + modelClass, e); } catch (InstantiationException e) { throw new RuntimeException("A " + modelClass + " cannot be instantiated.", e); } catch (InvocationTargetException e) { throw new RuntimeException("An exception happened in constructor of " + modelClass, e.getCause()); } } private static Application checkApplication(Activity activity) { Application application = activity.getApplication(); if (application == null) { throw new IllegalStateException("Your activity/fragment is not yet attached to " + "Application. You can't request ViewModel before onCreate call."); } return application; } private static Activity checkActivity(Fragment fragment) { Activity activity = fragment.getActivity(); if (activity == null) { throw new IllegalStateException("Can't create ViewModelProvider for detached fragment"); } return activity; } private static final Class<?>[] ACCOUNT_ANDROID_VIEW_MODEL_SIGNATURE = new Class[]{Application.class, SavedStateHandle.class, TCAccountContext.class}; private static final Class<?>[] ANDROID_VIEW_MODEL_SIGNATURE = new Class[]{Application.class, SavedStateHandle.class}; private static final Class<?>[] ACCOUNT_VIEW_MODEL_SIGNATURE = new Class[]{SavedStateHandle.class, TCAccountContext.class}; private static final Class<?>[] VIEW_MODEL_SIGNATURE = new Class[]{SavedStateHandle.class}; @SuppressWarnings("unchecked") private static <T> Constructor<T> findMatchingConstructor(Class<T> modelClass, Class<?>[] signature) { for (Constructor<?> constructor : modelClass.getConstructors()) { Class<?>[] parameterTypes = constructor.getParameterTypes(); if (Arrays.equals(signature, parameterTypes)) { return (Constructor<T>) constructor; } } return null; } }
10-31
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值