操作栏

时间:2015-07-04 16:47:34

标签: android android-fragments android-asynctask

所以我开始创建一个使用jsoup废弃股票数据的应用程序。当我从家庭活动转移到' Stocks'通过导航抽屉的活动,我要求生成的活动显示第一个片段(在viewpager中的recyclerview),它会擦除​​并列出所有股票。但是,这总是会导致以下错误。但是,如果将片段作为第三个片段放置并打开,如下图所示(编辑:无法发布图片),它将按预期工作。

  

9200-9200 / com.blueinklabs.investmentportfoliopakistan   E / AndroidRuntime:FATAL EXCEPTION:主要流程:   com.blueinklabs.investmentportfoliopakistan,PID:9200   java.lang.NullPointerException:尝试调用接口方法   ' android.view.MenuItem android.view.MenuItem.setVisible(boolean)'在...上   null对象引用   com.blueinklabs.investmentportfoliopakistan.StocksActivity.showProgressBar(StocksActivity.java:68)   在   com.blueinklabs.investmentportfoliopakistan.StockData $ Title.onPreExecute(StockData.java:37)   在android.os.AsyncTask.executeOnExecutor(AsyncTask.java:591)at   android.os.AsyncTask.execute(AsyncTask.java:539)at   com.blueinklabs.investmentportfoliopakistan.StockData。(StockData.java:28)   在   com.blueinklabs.investmentportfoliopakistan.StocksCompleteListFragment.getSymbols(StocksCompleteListFragment.java:63)   在   com.blueinklabs.investmentportfoliopakistan.StocksCompleteListFragment.setupRecyclerView(StocksCompleteListFragment.java:55)   在   com.blueinklabs.investmentportfoliopakistan.StocksCompleteListFragment.onCreateView(StocksCompleteListFragment.java:48)   在   android.support.v4.app.Fragment.performCreateView(Fragment.java:1789)   在   android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:955)   在   android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1138)   在   android.support.v4.app.BackStackRecord.run(BackStackRecord.java:740)   在   android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1501)   在   android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:490)   在   在android.support.v4.view.ViewPager.populate(ViewPager.java:1105)的android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:141)   android.support.v4.view.ViewPager.populate(ViewPager.java:951)at   android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1473)at   android.view.View.measure(View.java:17547)at   android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5535)at   android.support.design.widget.CoordinatorLayout.onMeasureChild(CoordinatorLayout.java:573)   在   android.support.design.widget.CoordinatorLayout.onMeasure(CoordinatorLayout.java:640)   在android.view.View.measure(View.java:17547)处   android.support.v4.widget.DrawerLayout.onMeasure(DrawerLayout.java:868)   在android.view.View.measure(View.java:17547)处   android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5535)at   android.widget.FrameLayout.onMeasure(FrameLayout.java:436)at   android.support.v7.internal.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:124)   在android.view.View.measure(View.java:17547)处   android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5535)at   android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1436)   在android.widget.LinearLayout.measureVertical(LinearLayout.java:722)   在android.widget.LinearLayout.onMeasure(LinearLayout.java:613)at   android.view.View.measure(View.java:17547)at   android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5535)at   android.widget.FrameLayout.onMeasure(FrameLayout.java:436)at   android.view.View.measure(View.java:17547)at   android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5535)at   android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1436)   在android.widget.LinearLayout.measureVertical(LinearLayout.java:722)   在android.widget.LinearLayout.onMeasure(LinearLayout.java:613)at   android.view.View.measure(View.java:17547)at   android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5535)at   android.widget.FrameLayout.onMeasure(FrameLayout.java:436)at   com.android.internal.policy.impl.PhoneWindow $ DecorView.onMeasure(PhoneWindow.java:2615)   在android.view.View.measure(View.java:17547)处   android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2015)at   android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1173)at   android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1379)at   android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1061)at   android.view.ViewRootImpl $ TraversalRunnable.run(ViewRootImpl.java:588

我认为问题是异步任务(下面)在onPrepareOptionsMenu加载之前发生。错误发生在下面的类中的PreExecute:

import android.content.Context;
import android.os.AsyncTask;
import android.support.v7.widget.RecyclerView;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.IOException;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Iterator;

public class StockData {
    private ArrayList<String> symbolList;
    Context myContext;
    RecyclerView recyclerV;

    public StockData(Context getcontext, RecyclerView recyclerView){
        myContext = getcontext;
        symbolList = new ArrayList<String>();
        recyclerV = recyclerView;
        new Title().execute();
    }

    private class Title extends AsyncTask<Void, Void, Void> {
        String title;

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            ((StocksActivity) myContext).showProgressBar();
        }

        @Override
        protected Void doInBackground(Void... params) {
            Document doc = null;
            try {
                doc = Jsoup.connect("websiteurl").get();
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            Element table = doc.select("table.mGrid").get(1);
            Elements rows = table.select("tr");
            Iterator<Element> rowIterator = rows.iterator();
            rowIterator.next();

            while (rowIterator.hasNext()) {
                Element row = rowIterator.next();
                Elements cols = row.select("td");
                symbolList.add(cols.get(1).text());
            }
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            ((StocksCompleteListFragment.SimpleStringRecyclerViewAdapter) recyclerV.getAdapter()).changeList(symbolList);
            ((StocksActivity) myContext).hideProgressBar();
        }
    }

    public ArrayList<String> getSymbolList(){
        return symbolList;
    }


}

StocksActivity.java如下:

import android.content.Intent;
import android.graphics.Typeface;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.NavigationView;
import android.support.design.widget.Snackbar;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.GravityCompat;
import android.support.v4.view.MenuItemCompat;
import android.support.v4.view.ViewPager;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

/**
 * TODO
 */
public class StocksActivity extends AppCompatActivity {

    private DrawerLayout mDrawerLayout;
    public MenuItem miActionProgressItem;

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        // Store instance of the menu item containing progress
        miActionProgressItem = menu.findItem(R.id.mi_ActionProgress);
        // Extract the action-view from the menu item
        ProgressBar v = (ProgressBar) MenuItemCompat.getActionView(miActionProgressItem);
        // Return to finish
        Toast.makeText(this, "Hi", Toast.LENGTH_SHORT).show();
        return super.onPrepareOptionsMenu(menu);
    }

    public void showProgressBar() {
        // Show progress item
        miActionProgressItem.setVisible(true);
    }

    public void hideProgressBar() {
        // Hide progress item
        miActionProgressItem.setVisible(false);
    }

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

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        final ActionBar ab = getSupportActionBar();
        ab.setHomeAsUpIndicator(R.drawable.ic_menu);
        ab.setDisplayHomeAsUpEnabled(true);

        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);

        final NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        if (navigationView != null) {
            setupDrawerContent(navigationView);
            final Menu navMenu = navigationView.getMenu();
            ((MenuItem) navMenu.findItem(R.id.menuItem1)).setChecked(true);
            final ArrayList<View> mMenuItems = new ArrayList<>(navigationView.getChildCount());
            //for (int i = 0; i < navigationView.getChildCount(); i++){
            navigationView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() {
                    // Remember to remove the installed OnGlobalLayoutListener
                    navigationView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                    // Loop through and find each MenuItem View
                    for (int i = 0; i < 6; i++) {
                        final String id = "menuItem" + (i);
                        final MenuItem item = navMenu.findItem(getResources().getIdentifier(id, "id", getPackageName()));
                        navigationView.findViewsWithText(mMenuItems, item.getTitle(), View.FIND_VIEWS_WITH_TEXT);
                    }
                    // Loop through each MenuItem View and apply your custom Typeface
                    for (final View menuItem : mMenuItems) {
                        ((TextView) menuItem).setTypeface(null, Typeface.BOLD);
                        ((TextView) menuItem).setTextSize(14);
                    }
                }
            });
            //}

        }

        ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
        if (viewPager != null) {
            setupViewPager(viewPager);
        }

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Here's a Snackbar", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });

        TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
        tabLayout.setupWithViewPager(viewPager);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.sample_actions, menu);
        miActionProgressItem = menu.findItem(R.id.mi_ActionProgress);
        // Extract the action-view from the menu item
        ProgressBar v = (ProgressBar) MenuItemCompat.getActionView(miActionProgressItem);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                mDrawerLayout.openDrawer(GravityCompat.START);
                return true;
        }
        return super.onOptionsItemSelected(item);
    }

    private void setupViewPager(ViewPager viewPager) {
        Adapter adapter = new Adapter(getSupportFragmentManager());
        adapter.addFragment(new StocksCompleteListFragment(), "Category 1");
        adapter.addFragment(new CheeseListFragment(), "Category 2");
        adapter.addFragment(new CheeseListFragment(), "All Stocks");
        viewPager.setAdapter(adapter);
    }

    private void setupDrawerContent(NavigationView navigationView) {
        navigationView.setNavigationItemSelectedListener(
                new NavigationView.OnNavigationItemSelectedListener() {
                    @Override
                    public boolean onNavigationItemSelected(MenuItem menuItem) {
                        mDrawerLayout.closeDrawers();
                        switch (menuItem.getItemId()) {
                            case R.id.menuItem0:
                                Intent mainIntent = new Intent(getApplicationContext(), MainActivity.class);
                                startActivity(mainIntent);
                                finish();
                                break;
                            case R.id.menuItem1:
                                Intent stocksIntent = new Intent(getApplicationContext(), StocksActivity.class);
                                startActivity(stocksIntent);
                                finish();
                                break;
                        }
                        return true;
                    }
                });
    }

    @Override
    public void onBackPressed() {
        Intent mainIntent = new Intent(getApplicationContext(), MainActivity.class);
        startActivity(mainIntent);
        finish();
    }

    static class Adapter extends FragmentPagerAdapter {
        private final List<Fragment> mFragments = new ArrayList<>();
        private final List<String> mFragmentTitles = new ArrayList<>();

        public Adapter(FragmentManager fm) {
            super(fm);
        }

        public void addFragment(Fragment fragment, String title) {
            mFragments.add(fragment);
            mFragmentTitles.add(title);
        }

        @Override
        public Fragment getItem(int position) {
            return mFragments.get(position);
        }

        @Override
        public int getCount() {
            return mFragments.size();
        }

        @Override
        public CharSequence getPageTitle(int position) {
            return mFragmentTitles.get(position);
        }
    }
}

我花了最近8个小时试图解决这个问题,这是我第一次在这个论坛发帖,所以请原谅我是否错误地发布了这个。我已经搜索并尝试了一些我认为相关的解决方案。

http://i.stack.imgur.com/Wxxr6.png

编辑:继承人片段StocksCompleteListFragment.java的类

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.bumptech.glide.Glide;

import java.util.ArrayList;
import java.util.List;

public class StocksCompleteListFragment extends Fragment {

    ArrayList<String> list;
    RecyclerView rv;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        rv = (RecyclerView) inflater.inflate(
                R.layout.fragment_stocks_completelist, container, false);
        setupRecyclerView(rv);
        return rv;
    }

    private void setupRecyclerView(RecyclerView recyclerView) {
        recyclerView.setLayoutManager(new LinearLayoutManager(recyclerView.getContext()));
        recyclerView.setAdapter(new SimpleStringRecyclerViewAdapter(getActivity(),
                getSymbols(recyclerView)));

    }


    private ArrayList<String> getSymbols(RecyclerView recyclerView) {

        list = new ArrayList<>();
        StockData stockDataClass = new StockData(getActivity(), recyclerView);
        list = stockDataClass.getSymbolList();
        return list;
    }

    public static class SimpleStringRecyclerViewAdapter
            extends RecyclerView.Adapter<SimpleStringRecyclerViewAdapter.ViewHolder> {

        private final TypedValue mTypedValue = new TypedValue();
        private int mBackground;
        private List<String> mValues;

        public static class ViewHolder extends RecyclerView.ViewHolder {
            public String mBoundString;

            public final View mView;
            public final ImageView mImageView;
            public final TextView mTextView;

            public ViewHolder(View view) {
                super(view);
                mView = view;
                mImageView = (ImageView) view.findViewById(R.id.avatar);
                mTextView = (TextView) view.findViewById(android.R.id.text1);
            }

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

        public void changeList (ArrayList<String> tempStringList) {
            mValues = tempStringList;
            notifyDataSetChanged();
        }

        public String getValueAt(int position) {
            return mValues.get(position);
        }

        public SimpleStringRecyclerViewAdapter(Context context, List<String> items) {
            context.getTheme().resolveAttribute(R.attr.selectableItemBackground, mTypedValue, true);
            mBackground = mTypedValue.resourceId;
            mValues = items;
        }

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

        @Override
        public void onBindViewHolder(final ViewHolder holder, int position) {
            holder.mBoundString = mValues.get(position);
            holder.mTextView.setText(mValues.get(position));

            holder.mView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Context context = v.getContext();
                    Intent intent = new Intent(context, CheeseDetailActivity.class);
                    intent.putExtra(CheeseDetailActivity.EXTRA_NAME, holder.mBoundString);

                    context.startActivity(intent);
                }
            });

            Glide.with(holder.mImageView.getContext())
                    .load(Cheeses.getRandomCheeseDrawable())
                    .fitCenter()
                    .into(holder.mImageView);
        }

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

1 个答案:

答案 0 :(得分:0)

在评论中解释它可能很难解释,所以我会帮你调试这个答案。

因此,StockActivity加载片段,StocksCompleteListFragment执行AsyncTask(最后一个访问StockActivity的菜单项)。 AsyncTaskStockData的内部类)应该会收到对MenuItem的引用。

我会尝试,就像我之前告诉你的那样,将两种方法都移到MenuItem移动到AsyncTask

private class Title extends AsyncTask<Void, Void, Void> {
    // ...

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        showProgressBar();
    }

    @Override
    protected void onPostExecute(Void result) {
        ((StocksCompleteListFragment.SimpleStringRecyclerViewAdapter) recyclerV.getAdapter()).changeList(symbolList);
        hideProgressBar();
    }


    // I don't need them to be public if I move them here
    //
    private void showProgressBar() {
    // Show progress item
        item.setVisible(true);
    }

    private void hideProgressBar() {
        // Hide progress item
        item.setVisible(false);
    }
}

之后,您应该将MenuItem传递给StocksCompleteListFragment所以:

添加一个接收它的构造函数

public class StocksCompleteListFragment extends Fragment {
    private MenuItem item;

    // Default constructor
    public StocksCompleteListFragment() {}

    public StocksCompleteListFragment(MenuItem item) {
        this.item = item;
    }

    // ...  

然后将其传递给Fragment类

// StocksActivity.java

adapter.addFragment(new StocksCompleteListFragment(miActionProgressItem ), "Category 1");

稍后将该项从StocksCompleteListFragment传递到StockData类,以便内部AsyncTask可以访问它

public class StockData {
    private ArrayList<String> symbolList;
    Context myContext;
    RecyclerView recyclerV;
    private MenuItem item;

    public StockData(Context getcontext, RecyclerView recyclerView){
        myContext = getcontext;
        symbolList = new ArrayList<String>();
        recyclerV = recyclerView;
        new Title().execute();
    }

    public StockData(Context getcontext, RecyclerView recyclerView, MenuItem item) {
        this(getcontext, recyclerView);
        this.item = item;
    }

最后编辑你的代码片段,调用AsyncTask来传递MenuItem

private ArrayList<String> getSymbols(RecyclerView recyclerView) {

    list = new ArrayList<>();
    StockData stockDataClass = new StockData(getActivity(), recyclerView, item);
    list = stockDataClass.getSymbolList();
    return list;
}

如果我走在正确的轨道上,当您致电MenuItem时,AsyncTask应该已经存在。 我是这样看的:

StockActivity (完全加载,操作栏和所有内容) - &gt;传递菜单项 - &gt; StocksCompleteListFragment (调用AsyncTask) - &gt;传递菜单项 - &gt; AsyncTask 隐藏/显示菜单项。

这就是我的看法,必须有一个更简单的选择,但我无法想出更轻松的事情。

试试这个,我宁愿这是一个评论而不是一个答案,但我不能写这么多。

继续尝试,明天我会回来跟踪这个帖子。我希望它对你有所帮助。