如何使用 Dagger 2 在 Activity 或 Fragment 范围内交换测试双精度?

2023-12-24

编辑:小心!我已经删除了这个问题中提到的旧存储库。请参阅我自己对问题的回答以获取可能的解决方案,并随时改进它!

我指的是我的帖子here https://stackoverflow.com/questions/40405839/dagger-2-dependency-injection-in-android-testcase。现在我更进一步了。我还指的是我的 github 项目中的两个分支:

  • 实验[分支号] 1](存储库已删除)
  • 实验[分支号] 2](存储库已删除)

在旧帖子中,我尝试将仪器测试中的组件交换为测试组件。如果我有一个ApplicationComponent,处于单例范围内。但确实如此not工作,如果我有ActivityComponent具有自定义的@PerActivity范围。问题是not范围,但将 Component 交换到 TestComponent。

My ActivityComponent has an ActivityModule:

@PerActivity
@Component(modules = ActivityModule.class)
public interface ActivityComponent {
    // TODO: Comment this out for switching back to the old approach
    void inject(MainFragment mainFragment);
    // TODO: Leave that for witching to the new approach
    void inject(MainActivity mainActivity);
}

ActivityModule提供了一个MainInteractor

@Module
public class ActivityModule {
    @Provides
    @PerActivity
    MainInteractor provideMainInteractor () {
        return new MainInteractor();
    }
}

My TestActivityComponent uses a TestActivityModule:

@PerActivity
@Component(modules = TestActivityModule.class)
public interface TestActivityComponent extends ActivityComponent {
    void inject(MainActivityTest mainActivityTest);
}

TestActvityModule提供了一个FakeInteractor :

@Module
public class TestActivityModule {
    @Provides
    @PerActivity
    MainInteractor provideMainInteractor () {
        return new FakeMainInteractor();
    }
}

My MainActivity has a getComponent()方法和一个setComponent()方法。对于后者,您可以将组件交换为仪器测试中的测试组件。这是活动:

public class MainActivity extends BaseActivity implements MainFragment.OnFragmentInteractionListener {


    private static final String TAG = "MainActivity";
    private Fragment currentFragment;
    private ActivityComponent activityComponent;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initializeInjector();


        if (savedInstanceState == null) {
            currentFragment = new MainFragment();
            addFragment(R.id.fragmentContainer, currentFragment);
        }

    }

    private void initializeInjector() {
        Log.i(TAG, "injectDagger initializeInjector()");

        activityComponent = DaggerActivityComponent.builder()
                .activityModule(new ActivityModule())
                .build();
        activityComponent.inject(this);
    }

    @Override
    public void onFragmentInteraction(final Uri uri) {

    }

    ActivityComponent getActivityComponent() {
        return activityComponent;
    }

    @VisibleForTesting
    public void setActivityComponent(ActivityComponent activityComponent) {
        Log.w(TAG, "injectDagger Only call this method to swap test doubles");
        this.activityComponent = activityComponent;
    }
} 

如您所见,此活动使用MainFragment. In onCreate()组件被注入的片段:

public class MainFragment extends BaseFragment implements MainView {

    private static final String TAG = "MainFragment";
    @Inject
    MainPresenter mainPresenter;
    private View view;

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

    @Override
    public void onCreate(Bundle savedInstanceState) {
        Log.i(TAG, "injectDagger onCreate()");
        super.onCreate(savedInstanceState);
        // TODO: That approach works
//        ((AndroidApplication)((MainActivity) getActivity()).getApplication()).getApplicationComponent().inject(this);
        // TODO: This approach is NOT working, see MainActvityTest
        ((MainActivity) getActivity()).getActivityComponent().inject(this);
    }
}

然后在测试中我交换了ActivityComponentTestApplicationComponent:

public class MainActivityTest{

    @Rule
    public ActivityTestRule<MainActivity> mActivityRule = new ActivityTestRule(MainActivity.class, true, false);

    private MainActivity mActivity;
    private TestActivityComponent mTestActivityComponent;

    // TODO: That approach works
//    private TestApplicationComponent mTestApplicationComponent;
//
//    private void initializeInjector() {
//        mTestApplicationComponent = DaggerTestApplicationComponent.builder()
//                .testApplicationModule(new TestApplicationModule(getApp()))
//                .build();
//
//        getApp().setApplicationComponent(mTestApplicationComponent);
//        mTestApplicationComponent.inject(this);
//    }

    // TODO: This approach does NOT work because mActivity.setActivityComponent() is called after MainInteractor has already been injected!
    private void initializeInjector() {
        mTestActivityComponent = DaggerTestActivityComponent.builder()
                .testActivityModule(new TestActivityModule())
                .build();

        mActivity.setActivityComponent(mTestActivityComponent);
        mTestActivityComponent.inject(this);
    }

    public AndroidApplication getApp() {
        return (AndroidApplication) InstrumentationRegistry.getInstrumentation().getTargetContext().getApplicationContext();
    }
    // TODO: That approach works

//    @Before
//    public void setUp() throws Exception {
//
//        initializeInjector();
//        mActivityRule.launchActivity(null);
//        mActivity = mActivityRule.getActivity();
//    }

    // TODO: That approach does not works because mActivity.setActivityComponent() is called after MainInteractor has already been injected!
    @Before
    public void setUp() throws Exception {
        mActivityRule.launchActivity(null);
        mActivity = mActivityRule.getActivity();
        initializeInjector();
    }


    @Test
    public void testOnClick_Fake() throws Exception {
        onView(withId(R.id.edittext)).perform(typeText("John"));
        onView(withId(R.id.button)).perform(click());
        onView(withId(R.id.textview_greeting)).check(matches(withText(containsString("Hello Fake"))));
    }

    @Test
    public void testOnClick_Real() throws Exception {
        onView(withId(R.id.edittext)).perform(typeText("John"));
        onView(withId(R.id.button)).perform(click());
        onView(withId(R.id.textview_greeting)).check(matches(withText(containsString("Hello John"))));
    }

}

Activity测试运行但是错误Component用来。这是因为活动和片段onCreate()在交换组件之前运行。

正如你所看到的,我有一个注释的旧方法,如果我绑定一个ApplicationComponent到应用程序类。这是有效的,因为我可以在开始活动之前构建依赖关系。但现在随着ActivityComponent我必须在初始化注入器之前启动该活动。因为否则我无法设置

mActivity.setActivityComponent(mTestActivityComponent);

because mActivity如果在注入器初始化后启动活动,则将为 null。 (看MainActivityTest)

那么我怎样才能拦截MainActivityMainFragment使用TestActivityComponent?


现在我通过混合一些示例发现如何交换 Activity 范围的组件和 Fragment 范围的组件。在这篇文章中,我将向您展示如何做到这两点。但我将更详细地描述如何在 InstrumentationTest 期间交换 Fragment 范围的组件。我的总代码托管在github https://github.com/unlimited101/SwappingTestDoubles。您可以运行MainFragmentTest类但要注意你必须设置de.xappo.presenterinjection.runner.AndroidApplicationJUnitRunner作为 Android Studio 中的 TestRunner。

现在我描述很快,如何用假交互器交换交互器。在这个例子中我试图尊重干净的架构 https://github.com/android10/Android-CleanArchitecture越多越好。但它们可能是一些小事情,稍微破坏了这个架构。所以请随意改进。

那么,让我们开始吧。首先你需要一个自己的 JUnitRunner:

/**
 * Own JUnit runner for intercepting the ActivityComponent injection and swapping the
 * ActivityComponent with the TestActivityComponent
 */
public class AndroidApplicationJUnitRunner extends AndroidJUnitRunner {
    @Override
    public Application newApplication(ClassLoader classLoader, String className, Context context)
            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        return super.newApplication(classLoader, TestAndroidApplication.class.getName(), context);
    }

    @Override
    public Activity newActivity(ClassLoader classLoader, String className, Intent intent)
            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        Activity activity = super.newActivity(classLoader, className, intent);
        return swapActivityGraph(activity);
    }

    @SuppressWarnings("unchecked")
    private Activity swapActivityGraph(Activity activity) {
        if (!(activity instanceof HasComponent) || !TestActivityComponentHolder.hasComponentCreator()) {
            return activity;
        }

        ((HasComponent<ActivityComponent>) activity).
                setComponent(TestActivityComponentHolder.getComponent(activity));

        return activity;
    }
}

In swapActivityGraph()在运行测试时创建活动之前(!),我为活动创建了一个替代 TestActivityGraph。然后我们必须创建一个TestFragmentComponent:

@PerFragment
@Component(modules = TestFragmentModule.class)
public interface TestFragmentComponent extends FragmentComponent{
    void inject(MainActivityTest mainActivityTest);

    void inject(MainFragmentTest mainFragmentTest);
}

该组件位于 Fragment 范围内。它有一个模块:

@Module
public class TestFragmentModule {
    @Provides
    @PerFragment
    MainInteractor provideMainInteractor () {
        return new FakeMainInteractor();
    }
}

原本的FragmentModule看起来像这样:

@Module
public class FragmentModule {
    @Provides
    @PerFragment
    MainInteractor provideMainInteractor () {
        return new MainInteractor();
    }
}

你看我用的是MainInteractor and a FakeMainInteractor。他们看起来都是这样的:

public class MainInteractor {
    private static final String TAG = "MainInteractor";

    public MainInteractor() {
        Log.i(TAG, "constructor");
    }

    public Person createPerson(final String name) {
        return new Person(name);
    }
}


public class FakeMainInteractor extends MainInteractor {
    private static final String TAG = "FakeMainInteractor";

    public FakeMainInteractor() {
        Log.i(TAG, "constructor");
    }

    public Person createPerson(final String name) {
        return new Person("Fake Person");
    }
}

现在我们使用自定义的FragmentTestRule用于测试独立于生产中包含该片段的活动的片段:

public class FragmentTestRule<F extends Fragment> extends ActivityTestRule<TestActivity> {
    private static final String TAG = "FragmentTestRule";
    private final Class<F> mFragmentClass;
    private F mFragment;

    public FragmentTestRule(final Class<F> fragmentClass) {
        super(TestActivity.class, true, false);
        mFragmentClass = fragmentClass;
    }

    @Override
    protected void beforeActivityLaunched() {
        super.beforeActivityLaunched();
        try {
            mFragment = mFragmentClass.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void afterActivityLaunched() {
        super.afterActivityLaunched();

        //Instantiate and insert the fragment into the container layout
        FragmentManager manager = getActivity().getSupportFragmentManager();
        FragmentTransaction transaction = manager.beginTransaction();

        transaction.replace(R.id.fragmentContainer, mFragment);
        transaction.commit();
    }


    public F getFragment() {
        return mFragment;
    }
}

That TestActivity很简单:

public class TestActivity extends BaseActivity implements
        HasComponent<ActivityComponent> {

    @Override
    protected void onCreate(@Nullable final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        FrameLayout frameLayout = new FrameLayout(this);
        frameLayout.setId(R.id.fragmentContainer);
        setContentView(frameLayout);
    }
}

但现在如何更换组件呢?有几个小技巧可以实现这一点。首先我们需要一个holder类来保存TestFragmentComponent:

/**
 * Because neither the Activity nor the ActivityTest can hold the TestActivityComponent (due to
 * runtime order problems we need to hold it statically
 **/
public class TestFragmentComponentHolder {
    private static TestFragmentComponent sComponent;
    private static ComponentCreator sCreator;

    public interface ComponentCreator {
        TestFragmentComponent createComponent(Fragment fragment);
    }

    /**
     * Configures an ComponentCreator that is used to create an activity graph. Call that in @Before.
     *
     * @param creator The creator
     */
    public static void setCreator(ComponentCreator creator) {
        sCreator = creator;
    }

    /**
     * Releases the static instances of our creator and graph. Call that in @After.
     */
    public static void release() {
        sCreator = null;
        sComponent = null;
    }

    /**
     * Returns the {@link TestFragmentComponent} or creates a new one using the registered {@link
     * ComponentCreator}
     *
     * @throws IllegalStateException if no creator has been registered before
     */
    @NonNull
    public static TestFragmentComponent getComponent(Fragment fragment) {
        if (sComponent == null) {
            checkRegistered(sCreator != null, "no creator registered");
            sComponent = sCreator.createComponent(fragment);
        }
        return sComponent;
    }

    /**
     * Returns true if a custom activity component creator was configured for the current test run,
     * false otherwise
     */
    public static boolean hasComponentCreator() {
        return sCreator != null;
    }

    /**
     * Returns a previously instantiated {@link TestFragmentComponent}.
     *
     * @throws IllegalStateException if none has been instantiated
     */
    @NonNull
    public static TestFragmentComponent getComponent() {
        checkRegistered(sComponent != null, "no component created");
        return sComponent;
    }
}

第二个技巧是使用holder来注册组件before甚至创建了片段。然后我们启动TestActivity跟我们FragmentTestRule。现在是第三个技巧,它与时间相关并且并不总是正确运行。Directly启动活动后我们得到Fragment例如通过询问FragmentTestRule。然后我们交换组件,使用TestFragmentComponentHolder并注入片段图。第四个技巧是我们只需等待大约 2 秒即可创建 Fragment。在 Fragment 中我们进行组件注入onViewCreated()。因为那时我们不会过早注入组件,因为onCreate() and onCreateView()之前被调用过。所以这是我们的MainFragment:

public class MainFragment extends BaseFragment implements MainView {

    private static final String TAG = "MainFragment";
    @Inject
    MainPresenter mainPresenter;
    private View view;

    // TODO: Rename and change types and number of parameters
    public static MainFragment newInstance() {
        MainFragment fragment = new MainFragment();
        return fragment;
    }

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

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

        //((MainActivity)getActivity()).getComponent().inject(this);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        view = inflater.inflate(R.layout.fragment_main, container, false);
        return view;
    }

    public void onClick(final String s) {
        mainPresenter.onClick(s);
    }

    @Override
    public void onViewCreated(final View view, @Nullable final Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        getComponent().inject(this);

        final EditText editText = (EditText) view.findViewById(R.id.edittext);
        Button button = (Button) view.findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(final View v) {
                MainFragment.this.onClick(editText.getText().toString());
            }
        });
        mainPresenter.attachView(this);
    }

    @Override
    public void updatePerson(final Person person) {
        TextView textView = (TextView) view.findViewById(R.id.textview_greeting);
        textView.setText("Hello " + person.getName());
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mainPresenter.detachView();
    }

    public interface OnFragmentInteractionListener {
        void onFragmentInteraction(Uri uri);
    }
}

我之前描述的所有步骤(第二个到第四个技巧)都可以在@Before带注释的setUp()-方法在此MainFragmentTest class:

public class MainFragmentTest implements
        InjectsComponent<TestFragmentComponent>, TestFragmentComponentHolder.ComponentCreator {

    private static final String TAG = "MainFragmentTest";
    @Rule
    public FragmentTestRule<MainFragment> mFragmentTestRule = new FragmentTestRule<>(MainFragment.class);

    public AndroidApplication getApp() {
        return (AndroidApplication) InstrumentationRegistry.getInstrumentation().getTargetContext().getApplicationContext();
    }

    @Before
    public void setUp() throws Exception {
        TestFragmentComponentHolder.setCreator(this);

        mFragmentTestRule.launchActivity(null);

        MainFragment fragment = mFragmentTestRule.getFragment();

        if (!(fragment instanceof HasComponent) || !TestFragmentComponentHolder.hasComponentCreator()) {
            return;
        } else {
            ((HasComponent<FragmentComponent>) fragment).
                    setComponent(TestFragmentComponentHolder.getComponent(fragment));

            injectFragmentGraph();

            waitForFragment(R.id.fragmentContainer, 2000);
        }
    }

    @After
    public void tearDown() throws  Exception {
        TestFragmentComponentHolder.release();
        mFragmentTestRule = null;
    }

    @SuppressWarnings("unchecked")
    private void injectFragmentGraph() {
        ((InjectsComponent<TestFragmentComponent>) this).injectComponent(TestFragmentComponentHolder.getComponent());
    }

    protected Fragment waitForFragment(@IdRes int id, int timeout) {
        long endTime = SystemClock.uptimeMillis() + timeout;
        while (SystemClock.uptimeMillis() <= endTime) {

            Fragment fragment = mFragmentTestRule.getActivity().getSupportFragmentManager().findFragmentById(id);
            if (fragment != null) {
                return fragment;
            }
        }
        return null;
    }

    @Override
    public TestFragmentComponent createComponent(final Fragment fragment) {
        return DaggerTestFragmentComponent.builder()
                .testFragmentModule(new TestFragmentModule())
                .build();
    }

    @Test
    public void testOnClick_Fake() throws Exception {
        onView(withId(R.id.edittext)).perform(typeText("John"));
        onView(withId(R.id.button)).perform(click());
        onView(withId(R.id.textview_greeting)).check(matches(withText(containsString("Hello Fake"))));
    }

    @Test
    public void testOnClick_Real() throws Exception {
        onView(withId(R.id.edittext)).perform(typeText("John"));
        onView(withId(R.id.button)).perform(click());
        onView(withId(R.id.textview_greeting)).check(matches(withText(containsString("Hello John"))));
    }


    @Override
    public void injectComponent(final TestFragmentComponent component) {
        component.inject(this);
    }
}

除了时间问题。此测试在我的环境中运行,在 API 级别为 23 的模拟 Android 上进行了 10 次测试中的 10 次。在运行 Android 6 的真实三星 Galaxy S5 Neo 设备上进行了 10 次测试中的 9 次。

正如我上面所写,您可以从以下位置下载整个示例github https://github.com/unlimited101/SwappingTestDoubles如果您找到解决时间问题的方法,请随意改进。

就是这样!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 Dagger 2 在 Activity 或 Fragment 范围内交换测试双精度? 的相关文章

  • React Native 从 JavaScript 代码内部访问 strings.xml

    有没有办法访问当前值android app src main res values strings xml从 JavaScript 代码内部 我想为每个构建放置不同的端点 URL 但我什至无法检测到反应本机代码内的构建类型 而不必求助于 D
  • 如何重试已消耗的 Observable?

    我正在尝试重新执行失败的已定义可观察对象 一起使用 Retrofit2 和 RxJava2 我想在单击按钮时重试特定请求及其订阅和行为 那可能吗 service excecuteLoginService url tokenModel Ret
  • Android - 从资产中解析巨大(超大)JSON 文件的最佳方法

    我正在尝试从资产文件夹中解析一些巨大的 JSON 文件 我如何加载并添加到 RecyclerView 我想知道解析这种大文件 大约 6MB 的最佳方法是什么 以及您是否知道可以帮助我处理此文件的良好 API 我建议您使用GSON lib h
  • 使用 typescript、karma 和 jasmine 进行 RxJS Observable.timer 单元测试

    大家好 我对 Angular2 Karma 和 Jasmine 还比较陌生 目前我正在使用 Angular 2 RC4 Jasmine 2 4 x 我有一个 Angular 2 服务 它定期调用 http 服务 如下所示 getDataFr
  • 如何以编程方式检查 AndroidManifest.xml 中是否声明了服务?

    我正在编写一个库 该库提供了一项服务 其他开发人员可以通过将其包含在他们的项目中来使用该服务 因此 我无法控制 AndroidManifest xml 我在文档中解释了要做什么 但一个常见的问题是人们忽略了将适当的 标记添加到其清单中 或者
  • 如何在android中获取Camera2 API的当前曝光

    In android hardware Camera旧的 我使用下面的代码获取当前曝光并获取它Camera Camera Parameters param mCamera getParameters currentExposure para
  • Android Activity 生命周期函数基础知识

    我正在测试这段代码 它显示活动所处的状态 public class Activity101Activity extends Activity String tag Lifecycle Called when the activity is
  • 找不到处理意图 com.instagram.share.ADD_TO_STORY 的活动

    在我们的 React Native 应用程序中 我们试图让用户根据视图 组件中的选择直接将特定图像共享到提要或故事 当我们尝试直接使用 com instagram share ADD TO FEED 进行共享时 它以一致的方式完美运行 但是
  • 在画布上绘图

    我正在编写一个 Android 应用程序 它可以在视图的 onDraw 事件上直接绘制到画布上 我正在绘制一些涉及单独绘制每个像素的东西 为此我使用类似的东西 for int x 0 x lt xMax x for int y 0 y lt
  • Angular 2和Jasmine单元测试:无法获取innerHtml

    我正在使用测试组件 WelcomeComponent 的示例之一 import Component OnInit from angular core import UserService from model user service Co
  • 控制Android的前置LED灯

    我试图在用户按下某个按钮时在前面的 LED 上实现 1 秒红色闪烁 但我很难找到有关如何访问和使用前置 LED 的文档 教程甚至代码示例 我的意思是位于 自拍 相机和触摸屏附近的 LED 我已经看到了使用手电筒和相机类 已弃用 的示例 但我
  • JavaMail 只获取新邮件

    我想知道是否有一种方法可以在javamail中只获取新消息 例如 在初始加载时 获取收件箱中的所有消息并存储它们 然后 每当应用程序再次加载时 仅获取新消息 而不是再次重新加载它们 javamail 可以做到这一点吗 它是如何工作的 一些背
  • 你的CPU不支持NX

    我刚刚下载了 android studio 但是我遇到了一个问题 当我运行它时 它说你的 cpu 不支持 NX 我应该怎么办 NX 或实际上是 NX 处理器位 是处理器的一项功能 有助于保护您的 PC 免受恶意软件的攻击 当此功能未启用并且
  • 如何使用 IF 检查 TextView 可见性

    我有一个 onCheckedChangeListener 来根据选择的单选按钮显示文本视图 我有 1 个疑问和 1 个难题 想知道是否有人可以帮助我 问题 您能否将单选组默认检查值设置为 否 单选按钮 以便一开始就不会检查任何内容 问题 如
  • Google 云端硬盘身份验证异常 - 需要许可吗? (v2)

    我一直在尝试将 Google Drive v2 添加到我的 Android 应用程序中 但无法获得授权 我收到 UserRecoverableAuthIOException 并显示消息 NeedPermission 我感觉 Google A
  • 如何默认在 ActionOpenDocument 意图中显示“内部存储”选项

    我需要用户选择一个自定义文件类型的文件 并将其从 Windows 文件资源管理器拖到 Android 设备上 但默认情况下内部存储选项不可用 当我使用以下命令启动意图时 var libraryIntent new Intent Intent
  • .isProviderEnabled(LocationManager.NETWORK_PROVIDER) 在 Android 中始终为 true

    我不知道为什么 但我的变量isNetowrkEnabled总是返回 true 我的设备上是否启用互联网并不重要 这是我的GPSTracker class public class GPSTracker extends Service imp
  • 在activity_main.xml中注释

    我是安卓新手 据我所知 XML 中的注释与 HTML 中的注释相同 使用 形式 我想在 Android 项目的 Activity main xml 配置文件中写一些注释 但它给了我错误 值得注意的是 我使用的是 Eclipse 但目前 我直
  • 将 Intent 包装在 LabeledIntent 中以用于显示目的

    要求 我的应用程序中有一个 共享 按钮 我需要通过 Facebook 分享 我需要选择是否安装原生 Facebook 应用程序 我们的决定是 如果未安装该应用程序 则将用户发送到 facebook com 进行分享 当前状态 我可以检测何时
  • android sdk 的位置尚未在 Windows 操作系统的首选项中设置

    在 Eclipse 上 我转到 windows gt Android SDK 和 AVD Manager 然后弹出此消息 Android sdk 的位置尚未在首选项中设置 进入首选项 在侧边栏找到 Android 然后会出现一个 SDK 位

随机推荐

  • 在 HTML5 中拖放的 JavaScript

    尝试在 HTML5 中执行一个简单的拖放示例 但是当我将图像放入 div 元素中时 出现以下错误 未捕获的类型错误 无法将属性 innerHTML 设置为 null 所以我假设错误消息意味着dragElement为空 我不明白为什么 因为我
  • @font-face 在 Android 版 Chrome 中不起作用

    我正在使用一个 font face声明在网站上调用字体并显示在IE FF Chrome 甚至移动 Safari 但是 该字体未显示在铬18 0 1025308 for 安卓 4 1 2 我使用的语法是字体弹簧的 http www fonts
  • ConcurrentHashMap的传递方法中,我不明白这两个条件“i >= n”和“i + n >= nextn”的含义

    在transfer方法中 判断扩展终止 或帮助传输线程完成 的条件是if i lt 0 i gt n i n gt nextn 我知道i lt 0这个条件意味着所有的bin都已经被分配了 但是我不明白其他两个条件的含义 i gt n and
  • 没有“Access-Control-Allow-Origin”客户端修复

    我正在尝试从 NFL 获取免费数据由suredbits提供的API http suredbits com api 不幸的是 在他们的标题中 他们没有添加Access Control Allow Origin 这会产生 CORS 问题 当我尝
  • 如何将 cin 与可变数量的输入一起使用?

    我昨天参加了一个编程比赛 我们必须读取表单的输入 n a1 a2 an m b1 b2 bm 其中第一行表示有多少个输入 下一行包含那么多输入 所有输入都是整数 我知道如果每行都有相同数量的输入 比如 3 我们可以写类似的内容 while
  • 使用urwid,如何通过按键一次显示一行?

    尝试创建一个简单的函数 当按下回车键或向下翻页键时 一次显示文本文件中的一行 我don t希望每次都能清除线路 换句话说 我需要暂停程序直到按下下一个按键 因为它只显示第一行 我尝试了一段时间 确实 没有成功 谢谢你的帮助 Handle k
  • 将 git lfs 存储库重置为指针

    我有一个git LFS https git lfs github com存储库已签出 所有的二进制文件都是pointers 我用以下方法提取了真正的二进制文件 git lfs pull include some binaries 我使用了二
  • 如何设置 grunt + browserify + tsify + babelify?

    我正在努力设置 grunt browserify tsify babelify 带调试 下面的 gruntfile 设置确实编译了 typescript 但没有发生 babel 转换 有人可以让我知道该怎么做吗 我可能需要使用 gulp 来
  • 使用 C 函数扩展 PostgreSQL 时实现高性能事务

    我的目标是实现将数据块从数据库复制到 C 函数中以进行处理并作为查询结果返回的最高性能 我是 PostgreSQL 的新手 目前正在研究移动数据的可能方法 具体来说 我正在寻找与 PostgreSQL 相关的细微差别或关键字 以快速移动大数
  • Laravel:在哪里存储全局数组数据和常量?

    我刚刚开始使用 Laravel 我需要重写几年前制作的整个系统 使用 Laravel 4 作为基础框架 在我的旧系统中 我曾经有一个constant php声明了一些常量的文件 以及globals php文件包含大量数组集 例如 类别状态
  • Babel:replaceWithSourceString 给出意外的标记 (1:1)

    我正在尝试替换动态 导入 语句 下面是一个检查导入是否以加号结尾的示例 module exports function babel return visitor ImportDeclaration function path state i
  • 如何获取Appium服务器日志

    有没有办法在测试脚本中获取 Appium 服务器日志 driver manage logs get appium server 或将 appium 服务器日志重定向到控制台 我的主要目的是单独获取仪器日志而不是所有日志 info debug
  • 有什么办法可以限制 Twitter 时间轴小部件中的推文吗?

    我正在使用 Twitter 的时间轴小部件 如下所示 并且希望将推文数量限制为 5 默认情况下为 20 该网站是为使用屏幕阅读器的视障人士而嵌入的 屏幕阅读器被困在小部件内 用户被迫通过 Tab 浏览所有 20 条推文才能退出 Twitte
  • 如何克隆 MemoryStream 对象?

    我有一个MemoryStream经过的对象Stream类型参数 Stream是 C 中的抽象类 我想克隆它以创建另一个单独的MemoryStream对象与原始对象的当前位置并创建一个新的XMLReader出来 所以我将能够阅读其内容 这就是
  • 取消引用 void 指针时的reinterpret_cast 行为

    在与某人争论他在评论中提出的建议时这个答案 https stackoverflow com a 21177728 241631 我遇到了一些 gcc4 8 和 VS2013 拒绝编译的代码 但 clang 很高兴地接受它并显示正确的结果 i
  • 如何强制 GHC 内联 FFI 调用?

    我制作了小型 C 模块来提高性能 但 GHC 不内联外部函数 并且调用成本消除了加速 例如 test h int inc int x test c include test h int inc int x return x 1 Test h
  • Haskell 树木地图

    我的树定义为 data Tree a Leaf a Node Tree a Tree a deriving Show 我还声明了一个测试树 myTree Node Node Leaf 1 Leaf 2 Leaf 3 我想要做的是创建一个函数
  • 接连显示 UIMenuController 的问题

    我正在使用 UIMenuController 的新自定义功能将 复制 以外的内容添加到菜单中 以便剪切并粘贴到 Web 视图中 我所做的就是获取对共享 UIMenuController 的引用 将 UIMenuItems 的 NSArray
  • 确定从 spacy 中提取的文本是否是一个完整的句子

    我们正在研究从 PDF 中提取的句子 问题是它包括标题 页脚 目录等 有没有办法确定我们将文档传递给spacy时得到的句子是否是一个完整的句子 有没有办法过滤句子的某些部分 例如标题 一个完整的句子至少包含一个主语 一个谓语 一个宾语 并以
  • 如何使用 Dagger 2 在 Activity 或 Fragment 范围内交换测试双精度?

    编辑 小心 我已经删除了这个问题中提到的旧存储库 请参阅我自己对问题的回答以获取可能的解决方案 并随时改进它 我指的是我的帖子here https stackoverflow com questions 40405839 dagger 2