当前位置: 首页 > 知识库问答 >
问题:

避免手动处理配置更改

邰勇军
2023-03-14

这个项目是可以在Android Studio中找到的Master/Detail流模板的扩展。不同之处在于,这个应用程序使用一个活动和一个管理三个片段的ViewPager。第三个片段是Master(list)片段,其中包含一个可单击的Recyview。当单击列表项时,它会用子(细节)片段切换该片段。

在项目工作时,我希望避免在清单中使用Android:configchanges=“OrientationKeyboardHidDensCreensize”。我该怎么做?

baseFragment.java

public class BaseFragment extends Fragment {

    public Bridge mBridget;

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        mBridget = (MainActivity) getActivity();
    }
}

接口:bridge.java

public interface Bridge {
    abstract void onBack();
}

ItemListFragment.java

public class ItemListFragment extends BaseFragment{

    private boolean mTwoPane = false;
    private PageFragmentListener mListener;

    public static ItemListFragment newInstance(PageFragmentListener listener) {
        ItemListFragment fragment = new ItemListFragment();
        fragment.mListener = listener;
        return fragment;
    }

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

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);

        LayoutInflater inflater = LayoutInflater.from(getActivity());
        populateViewForOrientation(inflater, (ViewGroup) getView());
    }

    private void populateViewForOrientation(LayoutInflater inflater, ViewGroup viewGroup) {
        viewGroup.removeAllViewsInLayout();
        View subview = inflater.inflate(R.layout.fragment_item_list, viewGroup);

        initLayout(subview);
    }

    public void initLayout(View root) {
        View recyclerView = root.findViewById(R.id.item_list);

        mTwoPane = false;
        if (root.findViewById(R.id.item_detail_container) != null) {        // R.layout.list_item is located "layout", "layout-land"..
            mTwoPane = true;            // currently loaded "layout-land/list_item".  landscape mode
        }

        Toolbar toolbar = (Toolbar) root.findViewById(R.id.toolbar);
        ((AppCompatActivity)getActivity()).setSupportActionBar(toolbar);
        toolbar.setTitle("List");
        assert recyclerView != null;
        setupRecyclerView((RecyclerView) recyclerView);
    }

    private void setupRecyclerView(RecyclerView recyclerView) {
        recyclerView.setAdapter(new SimpleItemRecyclerViewAdapter(DummyContent.ITEMS));
    }

    public class SimpleItemRecyclerViewAdapter
            extends RecyclerView.Adapter<SimpleItemRecyclerViewAdapter.ViewHolder> {

        private final List<DummyContent.DummyItem> mValues;

        public SimpleItemRecyclerViewAdapter(List<DummyContent.DummyItem> items) {
            mValues = items;
        }

        @Override
        public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.item_list_content, parent, false);
            return new ViewHolder(view);
        }

        @Override
        public void onBindViewHolder(final ViewHolder holder, int position) {
            holder.mItem = mValues.get(position);
            holder.mIdView.setText(mValues.get(position).id);
            holder.mContentView.setText(mValues.get(position).content);

            // One row of List.  define click event
            holder.mView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (mTwoPane) {     // landscape mode
                        Bundle arguments = new Bundle();
                        arguments.putString(Constants.ARG_ITEM_ID, holder.mItem.id);
                        ItemTwoDetailFragment fragment = ItemTwoDetailFragment.newInstance();
                        fragment.setArguments(arguments);

                        // show detail fragment to right side of screen
                        getActivity().getSupportFragmentManager().beginTransaction()
                                .replace(R.id.item_detail_container, fragment)
                                .commit();
                    } else {    // portrait mode
                        if (mListener!=null)
                            mListener.onSwitchToNextFragment(holder.mItem.id);      // switch detail fragment
                    }
                }
            });
        }

        @Override
        public int getItemCount() {
            return mValues.size();
        }

        public class ViewHolder extends RecyclerView.ViewHolder {
            public final View mView;
            public final TextView mIdView;
            public final TextView mContentView;
            public DummyContent.DummyItem mItem;

            public ViewHolder(View view) {
                super(view);
                mView = view;
                mIdView = (TextView) view.findViewById(R.id.id);
                mContentView = (TextView) view.findViewById(R.id.content);
            }

            @Override
            public String toString() {
                return super.toString() + " '" + mContentView.getText() + "'";
            }
        }
    }

}
/**
 * A fragment representing a single Item detail screen.
 * on handsets.
 */
public class ItemOneDetailFragment extends BaseFragment {

    private DummyContent.DummyItem mItem;

    /*
    Listener for switch fragment
     */
    private PageFragmentListener mListener;

    public static ItemOneDetailFragment newInstance(PageFragmentListener listener) {
        ItemOneDetailFragment fragment = new ItemOneDetailFragment();
        fragment.mListener = listener;
        return fragment;
    }

    public ItemOneDetailFragment() {
    }

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

        if (getArguments().containsKey(Constants.ARG_ITEM_ID)) {
            mItem = DummyContent.ITEM_MAP.get(getArguments().getString(Constants.ARG_ITEM_ID)); // Get selected Item ID to show details
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        View rootView = inflater.inflate(R.layout.fragment_item_one_detail, container, false);

        // Show the dummy content as text in a TextView.
        if (mItem != null) {

            Toolbar toolbar = (Toolbar) rootView.findViewById(R.id.detail_toolbar);
            toolbar.setTitle(mItem.content);
            toolbar.setNavigationIcon(R.drawable.ic_ab_back_material);
            toolbar.setNavigationOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    mBridget.onBack();
                }
            });

            ((TextView) rootView.findViewById(R.id.item_detail)).setText(mItem.details);    // show details
        }

        return rootView;
    }

}
// for landscape orientation
public class ItemTwoDetailFragment extends BaseFragment {

    private DummyContent.DummyItem mItem;


    public static ItemTwoDetailFragment newInstance() {
        return new ItemTwoDetailFragment();
    }

    public ItemTwoDetailFragment() {
    }

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

        if (getArguments().containsKey(Constants.ARG_ITEM_ID)) {
            mItem = DummyContent.ITEM_MAP.get(getArguments().getString(Constants.ARG_ITEM_ID));     // Get selected item to show details
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_item_two_detail, container, false);

        // Show the dummy content as text in a TextView.
        if (mItem != null) {
            ((TextView) rootView.findViewById(R.id.item_detail)).setText(mItem.details);        // show details
        }
        return rootView;
    }
}
public class MainActivity extends AppCompatActivity implements Bridge{

    private ViewPager viewPager = null;
    private MyAdapter mAdapter;
    PageChangeListener mListener = new PageChangeListener();

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

        viewPager = (ViewPager) findViewById(R.id.pager);
        viewPager.setOnPageChangeListener(mListener);       // Page Change Listener

        mAdapter = new MyAdapter(getSupportFragmentManager());
        viewPager.setAdapter(mAdapter);

        // Show the Up button in the action bar.
        ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) {
            actionBar.setDisplayHomeAsUpEnabled(true);
        }
    }

    @Override
    public void onBackPressed() {
        if (mListener.getCurrentPage()==2 && mAdapter.mFragment instanceof ItemOneDetailFragment) {     // current page is Tab-3, current fragment is detail fragment
            mAdapter.mListener.onSwitchToNextFragment("0");     // show List fragment
            return;     // prevent to finish app.
        }

        super.onBackPressed();
    }

    // Do the same thing as the back button - go back to ItemListFragment
    // Only when in ItemOneDetailFragment
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == android.R.id.home) {
            if (mListener.getCurrentPage() == 2 && mAdapter.mFragment instanceof ItemOneDetailFragment) {     // current page is Tab-3, current fragment is detail fragment
                mAdapter.mListener.onSwitchToNextFragment("0");     // show List fragment
//                return;     // prevent to finish app.
            }
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onBack() {
        onBackPressed();
    }
}

class PageChangeListener extends ViewPager.SimpleOnPageChangeListener {
    private int currentPage;

    @Override
    public void onPageSelected(int position) {
        currentPage = position;     // current selected page
    }

    public final int getCurrentPage() {
        return currentPage;
    }
}

/**
 * Fragment Page Adapter
 */
class MyAdapter extends FragmentPagerAdapter{

    private final FragmentManager mFragmentManager;
    public BaseFragment mFragment;

    /**
     *  PageFragmentListener for switching fragment.
     */
    public PageFragmentListener mListener = new PageFragmentListener() {
        @Override
        public void onSwitchToNextFragment(final String id) {
            mFragmentManager.beginTransaction().remove(mFragment).commit();
            if (mFragment instanceof ItemListFragment){     // current fragment is List Fragment
                Bundle arguments = new Bundle();
                arguments.putString(Constants.ARG_ITEM_ID, id);     // selected item id
                mFragment = ItemOneDetailFragment.newInstance(mListener);       // switch detail fragment
                mFragment.setArguments(arguments);
            }else{      // DetailFragment
                mFragment = ItemListFragment.newInstance(mListener);    // => switch list fragment
            }

            notifyDataSetChanged();     // notify changes
        }
    };

    public MyAdapter(FragmentManager fm) {
        super(fm);
        mFragmentManager = fm;
    }

    @Override
    public Fragment getItem(int position) {
        if (position == 0)      // Tab-1
            return FragmentA.newInstance();

        if (position == 1)      // Tab-2
            return FragmentB.newInstance();

        if (position == 2) {    // Tab-3
            if (mFragment==null)    // first time => create list fragment
                mFragment = ItemListFragment.newInstance(mListener);

            return mFragment;
        }

        return null;
    }


    @Override
    public CharSequence getPageTitle(int position) {
        if (position == 0) {    // Tab-1
            return "Tab 1";
        }
        if (position == 1) {    // Tab-2
            return "Tab 2";
        }
    if (position == 2) {        //Tab-3
            return "Tab 3";
        }
        return null;
    }

    @Override
    public int getCount() {     // Count of Tabs
        return 3;
    }

    @Override
    public int getItemPosition(Object object) {
        Log.i("Adapter", "ItemPosition>>>" + object.toString());
        if (object instanceof ItemListFragment && mFragment instanceof ItemOneDetailFragment) {     //  fragment changed
            return POSITION_NONE;
        }

        if (object instanceof ItemOneDetailFragment && mFragment instanceof ItemListFragment) {     // fragment changed
            return POSITION_NONE;
        }

        return POSITION_UNCHANGED;
    }
}
public interface PageFragmentListener {
    void onSwitchToNextFragment(String id);
}
First instantiation 
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: newInstance
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onCreate()
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onCreateView()
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: initLayout
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: setupRecyclerView()
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onBindViewHolder

ClickItem
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onClick(): single pane
03-16 .../com.allison.viewpagermasterdetail D/MyAdapter: removed fragment
03-16 .../com.allison.viewpagermasterdetail D/MyAdapter: is instance of List Fragment
03-16 .../com.allison.viewpagermasterdetail D/ItemOneDetailFragment: newInstance
03-16 .../com.allison.viewpagermasterdetail I/Adapter: ItemPosition>>>FragmentB{41dd3810 #1 id=0x7f0c0069 android:switcher:2131492969:1}
03-16 .../com.allison.viewpagermasterdetail I/Adapter: ItemPosition>>>ItemListFragment{41df1528 #2 id=0x7f0c0069 android:switcher:2131492969:2}
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onPause()
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onStop()
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onDestroyView()
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onDestroy()
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onPause()

Back
03-16 .../com.allison.viewpagermasterdetail D/MyAdapter: removed fragment
03-16 .../com.allison.viewpagermasterdetail D/MyAdapter: is instance of Detail Fragment
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: newInstance
03-16 .../com.allison.viewpagermasterdetail I/Adapter: ItemPosition>>>FragmentB{41dd3810 #1 id=0x7f0c0069 android:switcher:2131492969:1}
03-16 .../com.allison.viewpagermasterdetail I/Adapter: ItemPosition>>>ItemOneDetailFragment{41e896a8 #2 id=0x7f0c0069 android:switcher:2131492969:2}
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onCreate()
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onCreateView()
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: initLayout
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: setupRecyclerView()

Rotate
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onConfigurationChanged
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: populateViewForOrientation
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: initLayout
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: setupRecyclerView()
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onBindViewHolder

ClickItemLand
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onClick(): mTwoPane

Rotate
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onConfigurationChanged
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: populateViewForOrientation
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: initLayout
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: setupRecyclerView()
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onBindViewHolder

ClickIemPortrait
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onClick(): single pane
03-16 .../com.allison.viewpagermasterdetail D/MyAdapter: removed fragment
03-16 .../com.allison.viewpagermasterdetail D/MyAdapter: is instance of List Fragment
03-16 .../com.allison.viewpagermasterdetail D/ItemOneDetailFragment: newInstance
03-16 .../com.allison.viewpagermasterdetail I/Adapter: ItemPosition>>>FragmentB{41dd3810 #1 id=0x7f0c0069 android:switcher:2131492969:1}
03-16 .../com.allison.viewpagermasterdetail I/Adapter: ItemPosition>>>ItemListFragment{41ea8b68 #2 id=0x7f0c0069 android:switcher:2131492969:2}
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onPause()
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onStop()
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onDestroyView()
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onDestroy()
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onPause()
First instantiation 
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: newInstance
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onCreate()
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onCreateView()
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: initLayout
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: setupRecyclerView()
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onBindViewHolder

ClickItem
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onClick(): single pane
03-16 .../com.allison.viewpagermasterdetail D/MyAdapter: removed fragment
03-16 .../com.allison.viewpagermasterdetail D/MyAdapter: is instance of List Fragment
03-16 .../com.allison.viewpagermasterdetail D/ItemOneDetailFragment: newInstance
03-16 .../com.allison.viewpagermasterdetail I/Adapter: ItemPosition>>>FragmentB{41dd4758 #1 id=0x7f0c0069 android:switcher:2131492969:1}
03-16 .../com.allison.viewpagermasterdetail I/Adapter: ItemPosition>>>ItemListFragment{41ded998 #2 id=0x7f0c0069 android:switcher:2131492969:2}
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onPause()
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onStop()
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onDestroyView()
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onDestroy()
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onPause()

Back
03-16 .../com.allison.viewpagermasterdetail D/MyAdapter: removed fragment
03-16 .../com.allison.viewpagermasterdetail D/MyAdapter: is instance of Detail Fragment
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: newInstance
03-16 .../com.allison.viewpagermasterdetail I/Adapter: ItemPosition>>>FragmentB{41dd56b8 #1 id=0x7f0c0069 android:switcher:2131492969:1}
03-16 .../com.allison.viewpagermasterdetail I/Adapter: ItemPosition>>>ItemOneDetailFragment{41e830b8 #2 id=0x7f0c0069 android:switcher:2131492969:2}
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onCreate()
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onCreateView()
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: initLayout
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: setupRecyclerView()
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onBindViewHolder

Rotate
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onPause()
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onSaveInstanceState()
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onStop()
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onDestroyView()
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onDestroy()
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onPause()
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onCreate()
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onCreateView()
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: initLayout
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: setupRecyclerView()

ClickItemLand
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onClick(): mTwoPane

Rotate
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onPause()
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onSaveInstanceState()
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onStop()
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onDestroyView()
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onDestroy()
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onPause()
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onCreate()
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onCreateView()
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: initLayout
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: setupRecyclerView()
03-16 .../com.allison.viewpagermasterdetail E/ViewRootImpl: sendUserActionEvent() mView == null
03-16 .../com.allison.viewpagermasterdetail D/ItemListFragment: onBindViewHolder

ClickIemPortrait
// nothing happens

共有1个答案

楚宏胜
2023-03-14

您似乎有几个问题需要解决。

首先,当重新创建活动时,SimpleItemRecycerViewAdapter中指向MSistener的链接会中断。因此,您需要在活动重新创建后恢复该连接。要做到这一点,您需要做以下修复。

主要活动

public class MainActivity extends AppCompatActivity implements Bridge {
    ...
    PageChangeListener mListener = new PageChangeListener();
    //keep a reference to listener, need to access this from fragment
    PageFragmentListener mPageFragmentListener;
    ...

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

        mAdapter = new MyAdapter(getSupportFragmentManager());
        //set the listener
        mPageFragmentListener = mAdapter.mListener;
        ....
    }

}
public class ItemListFragment extends BaseFragment{
    ...
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        Activity activity = getActivity();
        if(activity instanceof MainActivity) {
            mListener = ((MainActivity)activity).mPageFragmentListener;
    }
    ...
}
public MyAdapter(FragmentManager fm) {
    super(fm);
    mFragmentManager = fm;
    List<Fragment> fragments = fm.getFragments();
    if(fragments != null) {
        for (Fragment f : fragments) {
            if (f instanceof ItemListFragment || f instanceof ItemOneDetailFragment) {
                mFragment = (BaseFragment) f;
            }
        }
    }
}

此时,您的代码应该可以工作了。但当您在查看列表项的详细信息时旋转设备时,它将崩溃。发生这种情况是因为您使用活动的fragmentManager直接从ItemlistFragment向活动添加子片段。相反,从片段本身使用childFragmentManager。

holder.mView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        if (mTwoPane) {     // landscape mode
        ...
        // show detail fragment to right side of screen
        getChildFragmentManager().beginTransaction()
            .replace(R.id.item_detail_container, fragment)
            .commit();
        } else {    // portrait mode
            ...
        }
    }
});
 类似资料:
  • 0.3 新版功能. 应用会需要某种配置。你可能会需要根据应用环境更改不同的设置,比如切换调试模 式、设置密钥、或是别的设定环境的东西。 Flask 被设计为需要配置来启动应用。你可以在代码中硬编码配置,这对于小的应用 并不坏,但是有更好的方法。 跟你如何载入配置无关,会有一个可用的配置对象保存着载入的配置值: Flask 对象的 config 属性。这是 Flask 自己放置特定配置值的地方,也是

  • 我们有一个用Spring Boot编写的REST API。这个应用程序的一部分是每天运行的Spring批处理作业。我希望Spring批处理作业完成后,一个退出代码返回到启动应用程序的shell脚本,因此我在main方法中添加了。我才意识到这会导致整个Spring Boot应用程序退出,而这是我们不想要的。我正在寻找一种方法来执行Spring批处理作业,向调用它的shell脚本返回退出代码,并使Sp

  • 问题内容: 我已经在C中实现了一些排序算法(用于对整数进行排序),并谨慎地用于存储与数据大小有关的任何内容(因此还包括了计数器和填充物),因为该算法也应使用数千兆字节的数据集进行测试整数 这些算法应该很好,并且分配的数据量应该没有问题:数据存储在文件中,并且每次仅加载很少的块,即使将内存中的缓冲区阻塞为任意大小,也可以正常工作。 使用数据集最多4千兆字节(因此16GB数据)的测试可以正常工作(排序

  • 我正在开发一个windows应用程序,它以600Hz的频率从传感器接收数据。在五分之二的情况下,我的IO线程成功地从传感器读取4字节的数据,并将其传递给GUI线程。 问题是五次中有三次,QSerialPort有无法解释的超时,其中QSerialPort的waitForReadyRead()返回false和serial。errorString()有超时错误。在这种情况下,它将永远不会读取数据。如果我

  • 我正在使用的SMS网关来响应客户传入的短信。 但是,我的处理需要相当长的时间(大约20秒),在此期间,我从Twilio收到一个超时。 我在想一个防止超时的方法。我怎样才能加快处理时间?耗时最长的部分是我上传一些图像。我在想我可以在不同的线程中启动这个过程。我的服务器只有一个核心,那么多线程会有好处吗?

  • 在模块化的Spring配置应用程序中,我们使用工厂bean跨模块边界提供bean实例。 例如,一个模块A可以通过名称name公开一个bean实例。然后,另一个模块B可以通过样式声明来使用该bean 请注意,模块具有分离的类加载器层次结构,并且A/name的实际实现类在B中可能不可见。就像在OSGI中一样(尽管这不是OSGi)。 我的目标是在 B 的编程应用程序上下文中提供 A/name。但是在尝试