【问题标题】:Can't change text after async task异步任务后无法更改文本
【发布时间】:2014-07-05 10:24:55
【问题描述】:

我正在开发安卓应用程序。它使用异步任务连接到互联网并获取 JSON 结果。之后,它将值保存到私有字符串变量。此任务适用于片段类中的按钮侦听器。单击按钮后,将执行异步任务。下一个命令是 setText 到 TextView。异步任务运行良好,但没有出现。如果我开始偏好活动然后回来,它就在那里。所以它有效,但它没有出现。也许我必须“重新绘制”屏幕,但我不知道如何。还是其他一些想法?请帮忙。

我在 Eclipse/Android 工作室中创建了基本的 android 项目,其中我有 MainActivity 类和 PlaceholderFragment 类正在扩展 Fragment(XML 中没有 Fragment 标记 - activity_main.xml 是 FrameLayout,fragment_main.xml 是线性布局)。首先类 PlaceholderFragment 是内部静态类,但我把它放到单独的 .java 文件中。看我的代码,我尽量简化:

MainActivity.java

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.Fragment;
import android.support.v7.app.ActionBarActivity;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends ActionBarActivity {

// URL to get JSON
private static String pref_url;
private static String pref_key;
private static String pref_check;

private String status = " ";

private static final String PARAM_KEY = "key";
private static final String PARAM_CODE = "code";
private static final String PARAM_CHECK = "check";

// JSON Node Names
private static final String TAG_STATUS = "status";

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

    if (savedInstanceState == null) {
        getSupportFragmentManager().beginTransaction()
                .add(R.id.container, new PlaceholderFragment()).commit();
    }
}

public void btnDoIt() {
    new JSONParse().execute();
}

public String getStatus() {
    return status;
}

public String createUrl() {
    String url = pref_url + "?" + PARAM_KEY + "=" + pref_key + "&"
            + PARAM_CODE + "=" + Code + "&" + PARAM_CHECK + "="
            + pref_check;
    return url;
}

 private class JSONParse extends AsyncTask<String, String, JSONObject> {
    private ProgressDialog pDialog;

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        pDialog = new ProgressDialog(MainActivity.this);
        pDialog.setMessage("Getting Data ...");
        pDialog.setIndeterminate(false);
        pDialog.setCancelable(true);
        pDialog.show();

    }

    @Override
    protected JSONObject doInBackground(String... args) {

        // Getting JSON from URL

        JSONParser jParser = new JSONParser();
        JSONObject json = jParser.getJSONFromUrl(createUrl());

        return json;

    }

    @Override
    protected void onPostExecute(JSONObject json) {
        pDialog.dismiss();
        try {
            // Storing JSON item in a Variable
            String vypis_key = json.getString(TAG_KEY);
            status = json.getString(TAG_STATUS);

            Toast toast = Toast.makeText(getApplicationContext(),
                    "//KEY = " + vypis_key, Toast.LENGTH_LONG);
            toast.show();   //it writes KEY = OK 

        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
}

PlaceholderFragment.java

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;

public class PlaceholderFragment extends Fragment {

View rootView;
Button btngetdata;


public PlaceholderFragment() {
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {

    rootView = inflater.inflate(R.layout.fragment_main, container, false);

    btngetdata = (Button) rootView.findViewById(R.id.btnUplatni);
    btngetdata.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            ((MainActivity) getActivity()).btnDoIt();
            setTextInTextView(getString(R.string.text_status) + " " + ((MainActivity) getActivity()).getStatus(), R.id.textstatus);
        }
    });

    return rootView;
}


@Override
public void onResume() {
    // TODO Auto-generated method stub
    super.onResume();
    setTextInTextView(getString(R.string.text_status) + " " + ((MainActivity) getActivity()).getStatus(), R.id.textstatus);
}

public void setTextInTextView(String text, int id) {
    TextView textView = (TextView) rootView.findViewById(id);
    textView.setText(text);
}

fragment_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="false"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.zonemedia.skener.PlaceholderFragment" >

    <TextView
        android:id="@+id/textstatus"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/text_status" />

    <Button
        android:id="@+id/btnUplatni"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/btn_Uplatni" />

</LinearLayout>

activity_main.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.zonemedia.skener.MainActivity"
tools:ignore="MergeRootFrame" >

【问题讨论】:

    标签: java android asynchronous android-fragments android-asynctask


    【解决方案1】:

    问题是你在onclick()中做了如下操作

           ((MainActivity) getActivity()).btnDoIt();
            setTextInTextView(getString(R.string.text_status) + " " + ((MainActivity)         getActivity()).getStatus(), R.id.textstatus);
    

    当第二条指令正在执行时,第一条指令(异步任务)仍在执行中。

    我建议您使用活动中的状态创建一个回调并在 asynctask 的 onPostExecute 中调用它,而不是在此回调中更改文本视图。

    【讨论】:

      【解决方案2】:

      您的 getStatus() 方法返回您设置的值为“”。

      尝试更新您的 onPostExecute 方法,将 status 的值设置为“vypis_key”变量的值。这将起作用,但仅在 AsyncTask 完成时才起作用,因此您需要想出一种方法来确保在更新 TextView 之前发生这种情况。

      【讨论】:

        【解决方案3】:

        你在 AsyncTask 的 onPostExecute 方法中更新状态。调用 AsyncTask 后获取状态,所以它不会更新状态文本。

        所以更新onPostExecute执行方法中的状态文本AsyncTask.i.e.

        简单的改变

        ((MainActivity) getActivity()).btnDoIt();
                setTextInTextView(getString(R.string.text_status) + " " + ((MainActivity) getActivity()).getStatus(), R.id.textstatus);
        

        ((MainActivity) getActivity()).btnDoIt();
        

        并将您的 onPostExecute 方法重写为

           @Override
            protected void onPostExecute(JSONObject json) {
                pDialog.dismiss();
                try {
                    // Storing JSON item in a Variable
                    String vypis_key = json.getString(TAG_KEY);
                    status = json.getString(TAG_STATUS);
        
                    Toast toast = Toast.makeText(getApplicationContext(),
                            "//KEY = " + vypis_key, Toast.LENGTH_LONG);
                    toast.show();   //it writes KEY = OK 
        
                    FragmentManager fm = getSupportFragmentManager();
                    PlaceholderFragment fragment = (PlaceholderFragmen)fm.findFragmentById(R.id.fragment_main);
                    fragment.setTextInTextView(getString(R.string.text_status) + " " + getStatus());
        } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        

        编辑

        在fragment的OncreateView方法中初始化textview,在Fragment类中声明为TextView textView;

         TextView textView;
         @Override
            public View onCreateView(LayoutInflater inflater, ViewGroup container,
                    Bundle savedInstanceState) {
        
                rootView = inflater.inflate(R.layout.fragment_main, container, false);
        
                textView = (TextView) rootView.findViewById(R.id.textstatus);
            //rest code
        

        并将setTextInTextViewmethod重写为

        public void setTextInTextView(String text) {
            textView.setText(text);
        }
        

        【讨论】:

        • 我正在考虑它,但请查看我的 xml 布局文件。我那里没有片段标签。我认为我可以通过 id 找到视图,而不是片段。我应该改变什么/我应该在哪里添加片段 ID?
        • @Brano_SR 没有标签为“fragment”,fragment_main 是您的片段,按照我的建议获取。
        • 我在 fragment_main.xml 的 LinearLayout 中添加了android:id="@+id/fragment_main"。我可以通过 id 找到片段,但我有错误:fragment.setTextInTextView(getString(R.string.text_status) + " " + getStatus(), R.id.textstatus); with reason: The method setTextInTextView(String,int) in undefined for the type Fragment.
        • 我试过了。结果是错误:PlaceholderFragment 类中的 NullPointerException,setTextInTextView 方法:` TextView textView = (TextView) rootView.findViewById(id); `
        • NullPointerException 再次上线fragment.setTextInTextView(getString(R.string.text_status) + " " + getStatus(), R.id.textstatus)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-12-06
        相关资源
        最近更新 更多