这是一种非常奇怪的行为,我不知道如何修复它。
我有一个作为演示者的活动(在MVP架构中)。当活动开始时,我附加一个片段作为视图。片段本身非常简单。
public class CurrentSaleFragment extends BaseFragment {
private MainMVP.SalesPresenterOps salesPresenterOps;
private SaleAdapter adapter;
private ListView lv;
@BindView(R.id.btn_sell)
FloatingActionButton btnAdd;
public static CurrentSaleFragment newInstance(){
CurrentSaleFragment fragment = new CurrentSaleFragment();
Bundle arguments = new Bundle();
arguments.putInt(LAYOUT_RES_ID, R.layout.fragment_quick_sale );
fragment.setArguments(arguments);
return fragment;
}
@Override
protected void init() {
super.init();
lv = (ListView)view.findViewById(R.id.lv_sale);
}
@OnClick(R.id.btn_sell)
public void addToSale(View view){
mPresenter.moveToFragment(SellProductFragment.newInstance());
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
salesPresenterOps = (MainMVP.SalesPresenterOps)context;
}
@Override
public void onDetach() {
salesPresenterOps = null;
super.onDetach();
}
}
此片段扩展的BaseFraank:
public class BaseFragment extends Fragment implements MainMVP.RequiredViewOps, View.OnClickListener,
LoaderRequiredOps{
protected View view;
protected MainMVP.PresenterOps mPresenter;
protected final static String LAYOUT_RES_ID = "layout_res_id";
@Override
public void showOperationResult(String message, final long rowId) {
Snackbar.make(view, message, Snackbar.LENGTH_LONG).setAction(
R.string.see, new View.OnClickListener() {
@Override
public void onClick(View v) {
onOperationResultClick(rowId);
}
}
).show();
}
@Override
public void showSnackBar(String msg) {
Snackbar.make(view, msg, Snackbar.LENGTH_SHORT).show();
}
@Override
public void showAlert(String msg) {}
protected void onOperationResultClick(long rowId){}
@Override
public void onAttach(Context context) {
super.onAttach(context);
mPresenter = (MainMVP.PresenterOps)context;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
this.view = inflater.inflate(getArguments().getInt(LAYOUT_RES_ID), null);
init();
return view;
}
protected void addToClickListener(View ... params){
for (View v : params){
v.setOnClickListener(this);
}
}
protected void init() {
if (view != null){
ButterKnife.bind(this, view);
}
}
@Override
public void onDetach() {
mPresenter = null;
Log.d(getClass().getSimpleName(), "Fragment was detached");
super.onDetach();
}
@Override
public void onClick(View v) {}
@Override
public void onPreLoad() {
Dialogs.buildLoadingDialog(getContext(), "Loading...").show();
}
@Override
public void onLoad() {}
@Override
public void onDoneLoading() {
Dialogs.dismiss();
}
}
当我输入“moveToFragment()”方法时,我只是将CurrentSaleFragment替换为一个新片段:
protected void addFragment(BaseFragment fragment){
mView = fragment;
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_holder,
fragment, null).addToBackStack(null).commit();
}
然后附上新的片段:
public class SellProductFragment extends BaseFragment{
private ListView listView;
private ProductListAdapter adapter;
private MainMVP.SalesPresenterOps mSalesPresenter;
public static SellProductFragment newInstance(){
SellProductFragment fragment = new SellProductFragment();
Bundle arguments = new Bundle();
arguments.putInt(LAYOUT_RES_ID, R.layout.fragment_inventory);
fragment.setArguments(arguments);
return fragment;
}
private void reload(){
final Loader loader = new Loader(this);
loader.execute();
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
mSalesPresenter = (MainMVP.SalesPresenterOps)context;
}
@Override
protected void init() {
super.init();
listView = (ListView)view.findViewById(R.id.lv_inventory);
reload();
FloatingActionButton button = (FloatingActionButton)view.findViewById(R.id.btn_add);
addToClickListener(button);
}
@Override
public void onLoad() {
adapter = new ProductListAdapter(getActivity().getApplicationContext(), R.layout.row_product_item,
mSalesPresenter.getProducts());
try{
updateListView();
}catch (Exception e){
Log.w(getClass().getSimpleName(), e.getMessage());
}
}
private void updateListView(){
if (adapter != null && listView != null){
listView.setAdapter(adapter);
}else{
throw new RuntimeException();
}
}
}
请参阅此片段也从BaseFraank扩展并实现Loader必备操作。该接口用于“加载”任何数据。加载完成后,它会添加一个对话框并更新适配器:
public class Loader extends AsyncTask<Void, Void, Void> {
private LoaderRequiredOps presenter;
public Loader(LoaderRequiredOps presenter){
this.presenter = presenter;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
presenter.onPreLoad();
}
@Override
protected Void doInBackground(Void... params) {
presenter.onLoad();
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
presenter.onDoneLoading();
presenter = null;
}
}
现在,当我尝试从SellProductFragment执行方法reload()时,我得到了“只有创建视图层次结构的原始线程才能接触其视图”
如果先附加SellProductFragment而不是CurrentSaleFragment,则不会发生这种情况。
这里到底发生了什么?
出于未知原因,未识别的配置允许在doInbackground()
方法上执行ListView
的适配器设置。将其移动到onPostExecute()
,现在它正在工作
您的Async Loader类在doInbackground()
期间从后台线程调用演示者方法onLoad()
。
我的猜测是在演示者的onLoad()
方法中,引用了一个视图。
为了在这一点上更改视图,将视图逻辑作为Runnable
发布到UI线程(您说您的演示者是活动,因此这应该可以从onLoad
方法)。
@Override
public void onLoad() {
runOnUiThread(new Runnable() {
@Override
public void run() {
// Your ui code here...
}
});
// Rest of your code here...
}
我有一个错误,只有创建视图层次结构的原始线程才能接触它的视图。但我不知道如何在多线程中处理ui,比如列表视图,我也不知道该放在哪里。
我正在使用MultipartEntityBuilder将图像发送到php服务器,我将图片和视频发送到设备摄像头的目录中,我需要将文件保存在新的ArrayList上并将其发送到php服务器。 总是报告错误: 我的代码 更新
我在Android中构建了一个简单的音乐播放器。每首歌的视图都包含一个SeekBar,实现如下: 这很好用。现在我想要一个计时器来计算歌曲进度的秒/分钟。因此,我在布局中放置了一个文本视图,在onCreate()中使用findViewById()获取它,并在。设置进度(pos): 但最后一行给了我一个例外: Android看法ViewRoot$CalledFromErrorThreadExcept
这是我所有的代码。
我正在为小应用程序设计UnitTest。这个应用程序说明您使用的是什么命理数字出生日期。我有一个问题,我该调用检查数字并将值放入TextView的方法。我有一个错误 ' 我的布局:` 我想测试的方法:'
我正在开发一个Android应用程序,我使用Eclipse作为IDE,我的数据库是MySQL。我有以下问题。当我试图通过AsynTask从数据库中获取数据时,出现了下面显示的错误。 活动: 异步任务: