これは非常に奇妙な動作で、私はそれを修正する方法がわかりません。ビュー階層を作成した元のスレッドのみがそのビューに触れることができます。 - 奇妙な振る舞い
私はプレゼンターとしての活動を持っています(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();
}
}
このfragmendが延びるBaseFragment:
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();
}
}
}
参照このフラグメントもBaseFragmentから拡張され、LoaderRequiredOpsを実装しています。インタフェースは、データをロードするために使用されます。私は、メソッドのリロードを()SellProductFragmentから私は、ビュー階層を作成し「のみ元のスレッドを取得し、実行しようとすると、今
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;
}
}
:それは、ダイアログおよび更新のロードが行われているアダプタを追加しますその意見に触れることができる。
これは、CurrentSaleFragmentの代わりにSellProductFragmentが最初にアタッチされている場合は発生しません。
ここで何が起こっているか
特定の構成で例外が発生しない場合は、ラッキー(?)になります。最終的に 'doInBackground()'の 'ListView'に' Adapter'を設定しています。あなたはそれをすることはできません。 –
あなたは正しいです!ありがとうございました。 'updateListView()'を 'onPostExecute()'に移動しました – chntgomez
ええ、そこには問題ありません。 'onPostExecute()'はUIスレッド上で動作します。 (私はあなたが 'doInBackground()'または 'onLoad()'から最小限の例のためにいくつかの処理コードを省略していると仮定していますが、そうでない場合、 'AsyncTask'それはむしろ無意味です。) –