所以我开始创建一个使用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();
}
}
}
答案 0 :(得分:0)
在评论中解释它可能很难解释,所以我会帮你调试这个答案。
因此,StockActivity
加载片段,StocksCompleteListFragment
执行AsyncTask
(最后一个访问StockActivity
的菜单项)。
AsyncTask
(StockData
的内部类)应该会收到对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 隐藏/显示菜单项。
这就是我的看法,必须有一个更简单的选择,但我无法想出更轻松的事情。
试试这个,我宁愿这是一个评论而不是一个答案,但我不能写这么多。
继续尝试,明天我会回来跟踪这个帖子。我希望它对你有所帮助。