异步任务刷新后尝试访问适配器时出现 nullPointer 异常
nullPointer exception when trying to access adapter after asynctask refresh
我正在观看一些关于制作天气应用程序的视频,但不知何故,我最终试图从我的操作栏下拉菜单中按下的按钮启动我的 AsyncTask
。现在 asynctask 是一个单独的 class 并且应用程序第一次加载 aynctask 很好但是当我尝试刷新并从我的操作栏菜单中的按钮重新启动异步任务时应用程序崩溃并显示 NullPointerException
:
07-18 00:45:05.615 5849-5849/johnpark.sunshine E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.NullPointerException
at johnpark.sunshine.MainActivityFragment.processFinish(MainActivityFragment.java:70)
at johnpark.sunshine.ForeCastLoader.onPostExecute(ForeCastLoader.java:39)
at johnpark.sunshine.ForeCastLoader.onPostExecute(ForeCastLoader.java:23)
at android.os.AsyncTask.finish(AsyncTask.java:631)
at android.os.AsyncTask.access0(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:644)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
再次尝试访问适配器时出现空指针异常。本质上,我的 Main activity 下拉菜单中有一个刷新按钮,它扩展了 ActionBar。当我单击该按钮时,它会调用 MainActivityFragment
class 中的一个方法,该方法会调用 ForeCastLoader asynctask
的执行方法。在 onPostExecute()
方法中,结果通过 processFinish()
方法传回片段。回到 ActivityFragment 中的那个方法,当尝试使用适配器时,我得到一个空指针异常。关于我做错了什么有什么想法吗?
主要活动
public class MainActivity extends ActionBarActivity
implements OnNavigationListener, android.support.v7.app.ActionBar.OnNavigationListener {
private final String TAG = this.getClass().getSimpleName();
private boolean mNaviFirstHit = true;
MainActivityFragment mfa;
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String[] dropdownValues = getResources().getStringArray(R.array.nav_list);
android.support.v7.app.ActionBar actionBar = getSupportActionBar();
ArrayAdapter<String> adapter = new ArrayAdapter<String>(actionBar.getThemedContext(),
android.R.layout.simple_spinner_item, android.R.id.text1,
dropdownValues);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
actionBar.setDisplayShowTitleEnabled(false);
actionBar.setNavigationMode(NAVIGATION_MODE_LIST);
actionBar.setListNavigationCallbacks(adapter, this);
}
@Override
public boolean onNavigationItemSelected(int position, long id) {
if (mNaviFirstHit) {
mNaviFirstHit = false;
return true;
}
if(position==1)
{
Intent in = new Intent(getApplicationContext(),SettingsActivity.class);
startActivity(in);
}
if(position==2)
{
mfa = new MainActivityFragment();
mfa.update();
}
return true;
}
}
MainActivityFragment
public class MainActivityFragment extends Fragment implements AsyncResponse{
private ArrayList <String> list = new ArrayList<>();
static ListView lv;
ForeCastLoader f = new ForeCastLoader();
ArrayAdapter<String> adapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
f.delegate = this;
adapter = new ArrayAdapter<String>(getActivity().getApplicationContext(),
R.layout.list_item_forecast,
R.id.list_item_forecast_textview, list);
f.execute("94043");
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
View v = inflater.inflate(R.layout.fragment_main, container, false);
lv = (ListView)v.findViewById(R.id.listview_forecast);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent in = new Intent(getActivity().getApplicationContext(), DetailView.class);
in.putExtra("tempData", adapter.getItem(position));
startActivity(in);
}
});
lv.setAdapter(adapter);
return v;
}
public void update()
{
f.delegate = this;
f.execute("97865");
}
public void processFinish(String[] output)
{
list.clear();
for(String s:output)
{
list.add(s);
}
adapter.notifyDataSetChanged();
lv.setAdapter(adapter);
}
我遗漏了 aSyncTask class 因为我已经正确知道它的返回值而且我不认为问题可能出在任何地方。
感谢您的帮助,我确定它只是忽略了一些东西。
当您单击刷新按钮时,我假设您正在使用 position =2
调用 MainActivity
中的 onNavigationItemSelected()
方法。在 if 条件内,您正在创建 MainActivityFragment
并调用它 update()
method.But 你的适配器正在 MainActivityFragment
中的 createView()
方法中初始化,它不会被调用,因为你没有调用 show()
在这个新片段上 instance.Try 调用现有片段本身的 update()
方法。
好吧,我可以看到您在单击 NavigationItem 时创建了一个新的 MainActivityFragment
。这样,新创建的 MainActivityFragment
不是您第一次启动应用程序时添加到 MainActivity
的那个。新的onCreate
方法没有被调用,所以无法访问里面的adapter
在 Activity
中访问先前添加的 Fragment
的正确方法是使用 FragmentManager
.
的 findFragmentByTag
方法
我假设您使用这样的标签添加 MainActivityFragment
。
transaction.add(id, maf, MainActivityFragmentTag);
添加后可以这样访问
if(position==2)
{
mfa = getSupportFragmentManager().findFragmentByTag(MainActivityFragmentTag);
mfa.update();
}
我正在观看一些关于制作天气应用程序的视频,但不知何故,我最终试图从我的操作栏下拉菜单中按下的按钮启动我的 AsyncTask
。现在 asynctask 是一个单独的 class 并且应用程序第一次加载 aynctask 很好但是当我尝试刷新并从我的操作栏菜单中的按钮重新启动异步任务时应用程序崩溃并显示 NullPointerException
:
07-18 00:45:05.615 5849-5849/johnpark.sunshine E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.NullPointerException
at johnpark.sunshine.MainActivityFragment.processFinish(MainActivityFragment.java:70)
at johnpark.sunshine.ForeCastLoader.onPostExecute(ForeCastLoader.java:39)
at johnpark.sunshine.ForeCastLoader.onPostExecute(ForeCastLoader.java:23)
at android.os.AsyncTask.finish(AsyncTask.java:631)
at android.os.AsyncTask.access0(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:644)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
再次尝试访问适配器时出现空指针异常。本质上,我的 Main activity 下拉菜单中有一个刷新按钮,它扩展了 ActionBar。当我单击该按钮时,它会调用 MainActivityFragment
class 中的一个方法,该方法会调用 ForeCastLoader asynctask
的执行方法。在 onPostExecute()
方法中,结果通过 processFinish()
方法传回片段。回到 ActivityFragment 中的那个方法,当尝试使用适配器时,我得到一个空指针异常。关于我做错了什么有什么想法吗?
主要活动
public class MainActivity extends ActionBarActivity
implements OnNavigationListener, android.support.v7.app.ActionBar.OnNavigationListener {
private final String TAG = this.getClass().getSimpleName();
private boolean mNaviFirstHit = true;
MainActivityFragment mfa;
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String[] dropdownValues = getResources().getStringArray(R.array.nav_list);
android.support.v7.app.ActionBar actionBar = getSupportActionBar();
ArrayAdapter<String> adapter = new ArrayAdapter<String>(actionBar.getThemedContext(),
android.R.layout.simple_spinner_item, android.R.id.text1,
dropdownValues);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
actionBar.setDisplayShowTitleEnabled(false);
actionBar.setNavigationMode(NAVIGATION_MODE_LIST);
actionBar.setListNavigationCallbacks(adapter, this);
}
@Override
public boolean onNavigationItemSelected(int position, long id) {
if (mNaviFirstHit) {
mNaviFirstHit = false;
return true;
}
if(position==1)
{
Intent in = new Intent(getApplicationContext(),SettingsActivity.class);
startActivity(in);
}
if(position==2)
{
mfa = new MainActivityFragment();
mfa.update();
}
return true;
}
}
MainActivityFragment
public class MainActivityFragment extends Fragment implements AsyncResponse{
private ArrayList <String> list = new ArrayList<>();
static ListView lv;
ForeCastLoader f = new ForeCastLoader();
ArrayAdapter<String> adapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
f.delegate = this;
adapter = new ArrayAdapter<String>(getActivity().getApplicationContext(),
R.layout.list_item_forecast,
R.id.list_item_forecast_textview, list);
f.execute("94043");
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
View v = inflater.inflate(R.layout.fragment_main, container, false);
lv = (ListView)v.findViewById(R.id.listview_forecast);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent in = new Intent(getActivity().getApplicationContext(), DetailView.class);
in.putExtra("tempData", adapter.getItem(position));
startActivity(in);
}
});
lv.setAdapter(adapter);
return v;
}
public void update()
{
f.delegate = this;
f.execute("97865");
}
public void processFinish(String[] output)
{
list.clear();
for(String s:output)
{
list.add(s);
}
adapter.notifyDataSetChanged();
lv.setAdapter(adapter);
}
我遗漏了 aSyncTask class 因为我已经正确知道它的返回值而且我不认为问题可能出在任何地方。 感谢您的帮助,我确定它只是忽略了一些东西。
当您单击刷新按钮时,我假设您正在使用 position =2
调用 MainActivity
中的 onNavigationItemSelected()
方法。在 if 条件内,您正在创建 MainActivityFragment
并调用它 update()
method.But 你的适配器正在 MainActivityFragment
中的 createView()
方法中初始化,它不会被调用,因为你没有调用 show()
在这个新片段上 instance.Try 调用现有片段本身的 update()
方法。
好吧,我可以看到您在单击 NavigationItem 时创建了一个新的 MainActivityFragment
。这样,新创建的 MainActivityFragment
不是您第一次启动应用程序时添加到 MainActivity
的那个。新的onCreate
方法没有被调用,所以无法访问里面的adapter
在 Activity
中访问先前添加的 Fragment
的正确方法是使用 FragmentManager
.
findFragmentByTag
方法
我假设您使用这样的标签添加 MainActivityFragment
。
transaction.add(id, maf, MainActivityFragmentTag);
添加后可以这样访问
if(position==2)
{
mfa = getSupportFragmentManager().findFragmentByTag(MainActivityFragmentTag);
mfa.update();
}