1

適切に設計されたオブジェクト指向システムを構築した経験はあまりありませんが、今回は即興で作成したため、システムが機能せず、エラーも発生しませんでした。

基本的に私の Android アプリには、ユーザー ID を使用してリモート データベースにクエリを実行し、ユーザー アバターとユーザー名の値を返すクラスを呼び出すユーザー プロファイル アクティビティがあります。

クラスがプロファイルアクティビティクラス内にネストされるまでは問題ありませんでしたが、そこから移動して他のものを変更することにしました。今ではマイプロファイルに移動すると、アバターが表示されず、ユーザー名も表示されません.

GetUserData クラスは次のとおりです。

public class GetUserData extends Activity {
    private String currentlyLoggedInUserString;
    SharedPreferences sharedPrefs;
    Editor editor;
    int currentlyLoggedInUser;
    private JSONParser jsonParser = new JSONParser();
    private Configurationz configurationz = new Configurationz();
    private ToastMaker toastMaker = new ToastMaker();
    private static final String TAG_SUCCESS = "success";
    private static final String TAG_USER_AVATAR = "user_avatar";
    private static final String TAG_USER_NAME = "user_name";
    private static final String TAG_USER_EMAIL = "user_email";
    private static final String TAG_USER_SEX = "user_sex";
    private static final String TAG_USER_DATE_REGISTERED = "user_date_registered";
    private static final String TAG_USER_LAST_SEEN = "user_last_seen";
    private static final String TAG_USER_PASSWORD = "user_password";
    private static final String APP_SHARED_PREFS = "asdasd_preferences";
    private String userName;
    private String userEmail;
    private String userSex;
    private String userPassword;
    private String userAvatar;
    private String userDateRegistered;
    private String userLastSeen;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getUserEmail() {
        return userEmail;
    }

    public void setUserEmail(String userEmail) {
        this.userEmail = userEmail;
    }

    public String getUserSex() {
        return userSex;
    }

    public void setUserSex(String userSex) {
        this.userSex = userSex;
    }

    public String getUserPassword() {
        return userPassword;
    }

    public void setUserPassword(String userPassword) {
        this.userPassword = userPassword;
    }

    public String getUserAvatar() {
        return userAvatar;
    }

    public void setUserAvatar(String userAvatar) {
        this.userAvatar = userAvatar;
    }

    public String getUserDateRegistered() {
        return userDateRegistered;
    }

    public void setUserDateRegistered(String userDateRegistered) {
        this.userDateRegistered = userDateRegistered;
    }

    public String getUserLastSeen() {
        return userLastSeen;
    }

    public void setUserLastSeen(String userLastSeen) {
        this.userLastSeen = userLastSeen;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        sharedPrefs = getApplicationContext().getSharedPreferences(APP_SHARED_PREFS, Context.MODE_PRIVATE);
        new GetUserDataGetter().execute();
    }

    public class GetUserDataGetter extends AsyncTask<String, String, String> {

        @Override
        protected String doInBackground(String... params) {
            int success;
            try {

                List<NameValuePair> parameters = new ArrayList<NameValuePair>();
                // fix these shitty variables.
                currentlyLoggedInUser = sharedPrefs.getInt("currentLoggedInUserId", 0);
                currentlyLoggedInUserString = Integer.toString(currentlyLoggedInUser);
                parameters.add(new BasicNameValuePair("user_id", currentlyLoggedInUserString));

                final JSONObject json = jsonParser.makeHttpRequest(configurationz.URL_PHP_GET_USER_DATA, "POST", parameters); 
                success = json.getInt(TAG_SUCCESS);
                if (success == 1) {
                    // user data found
                    setUserLastSeen(json.getString(TAG_USER_LAST_SEEN));
                    setUserDateRegistered(json.getString(TAG_USER_DATE_REGISTERED));
                    setUserAvatar(json.getString(TAG_USER_AVATAR));
                    setUserSex(json.getString(TAG_USER_SEX));
                    setUserPassword(json.getString(TAG_USER_PASSWORD));
                    setUserEmail(json.getString(TAG_USER_EMAIL));
                    setUserName(json.getString(TAG_USER_NAME));

                    //return json.getString(TAG_USER_AVATAR);
                    return null;
                } else if (success == 2) {
                    //toast about not being able to connect to db;
                    runOnUiThread(new Runnable() {
                        public void run() {

                            //this might cause some SHIT!!!!!!!!!!!! TEST IT!!!
                            toastMaker.toast(getBaseContext(), configurationz.ERROR_MESSAGES_SIGNUP_DEVICE_UNABLE_TO_TAKE_PHOTOS, configurationz, Toast.LENGTH_LONG);

                        }
                        });


                    setUserLastSeen("");
                    setUserDateRegistered("");
                    setUserAvatar("");
                    setUserSex("");
                    setUserPassword("");
                    setUserEmail("");
                    setUserName("");
                    return null;
                } else {

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

    }
}

MyProfile クラスは次のとおりです。

public class MyProfile extends ActionBarAndSlidingMenu {
    private TableRow myProfileActionButtonsHolder;
    private TextView tvUserName;
    private ImageButton iUserAvatar;
    private Bitmap iUserAvatarBitmap;
    private String avatarPath;
    private String userName;
    private static final String APP_SHARED_PREFS = "asdasd_preferences";
    SharedPreferences sharedPrefs;
    Editor editor;
    int currentlyLoggedInUser;
    boolean userLoggedInState = false;
    private GetUserData getUserData = new GetUserData();

    public MyProfile() {
        super(R.string.app_name);
    }

    // do a check here whether this is the user themselves or some other user

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        sharedPrefs = getApplicationContext().getSharedPreferences(APP_SHARED_PREFS, Context.MODE_PRIVATE);
        setContentView(R.layout.user_profile);

        // check whether user is logged in, otherwise redirect them to
        // login/signup page
        userLoggedInState = sharedPrefs.getBoolean("userLoggedInState", false);
        if (!userLoggedInState) {
            // start intent to get them out of here.
            // Research whether this step is necessary at all
        }

        // define the view components
        myProfileActionButtonsHolder = (TableRow) findViewById(R.id.userProfileActionButtonsHolder);

        // set avatar image
        iUserAvatar = (ImageButton) findViewById(R.id.iUserAvatar);
        avatarPath = getUserData.getUserAvatar();
        if (avatarPath != "") {
            iUserAvatarBitmap = BitmapFactory.decodeFile(avatarPath);
            iUserAvatar.setImageBitmap(iUserAvatarBitmap);
        } else {
            iUserAvatar.setImageResource(R.drawable.avatar_default_male);
        }

        //set user display name
        userName = getUserData.getUserName();
        tvUserName = (TextView) findViewById(R.id.tvUserName);
        tvUserName.setText(userName);


        // create action buttons fragment with "edit" and "settings" buttons
        getSupportFragmentManager().beginTransaction().replace(R.id.userProfileActionButtonsHolder, new MyProfileActionButtonsFragment()).commit();

    }
}
4

2 に答える 2

3

最初に、一般的なプログラミングと、特に適切なコーディングのガイドラインを読む必要があります。これは少し混乱しているためです。プロジェクトがより複雑になるとすぐに、これは判読不能になり、デバッグ不能になります。第二に、Android のしくみをよく読んでください。

一言で言えばあなたの問題は次のとおりです。

アクティビティは、Android 独自のクラスの単なるバージョンではなく、そのように使用することはできません。アクティビティは、ユーザーに表示される画面を表します。表示する画面がありませんか?活動なし。したがって、getUserData アクティビティは通常のクラスであり、アクティビティを拡張しないでください。

さて、 MyProfile では、メンバー変数を宣言するだけです

private GetUserData getUserData = new GetUserData();

これは何もせず、そのクラスの onCreate を実行することは決してありません。したがって、タスクは実行されず、すべてのフィールドが null を返します。

簡単に言うと、次のようにします。

  1. ユーザー名などを取得するコンストラクターと、これらの詳細を取得するために必要なゲッターを持つクラス UserDetails を作成します。他に何も追加しません。これは、値オブジェクトの Java バージョンと呼ばれるものです。

    public class UserDetails {
        private final String mUsername;
    
        public UserDetails(String username) {
             mUsername = username;
        }
    
        public String getUsername() {
            return mUsername;
        }
    }
    
  2. メソッド onUserDetailsReceived(UserDetails userDetails) を使用して IOnUserDetailsReceivedListener というインターフェイスを作成します。これは、ダウンロード タスクに時間がかかるためです。完了したら通知を受ける必要があり、それがこのインターフェースを使用する目的です。これをリスナーパターンと呼びます。

    public interface IOnUserDetailsReceivedListener {
        public void onUserDetailsReceived(UserDetails userDetails);
        public void onUserDetailsError();
    }
    
  3. AsyncTask を含み、メソッド retrieveUserDetails(); を持つクラス Downloader を作成します。か何か。そのメソッドで、非同期タスクを実行してダウンロードします。サーバーからデータを取得したら、それを新しい UserDetails(...) オブジェクトに入力してから、listener.onUserDetailsReceived(userDetails) を呼び出します。

    public class UserDetailsDownloader {
        private IOnUserDetailsReceivedListener mListener;
    
        public UserDetailsDownloader(IOnUserDetailsReceivedListener listener) {
            mListener = listener;
        }
    
        public void downloadUserDetails() {
            //Execute the async task here. In it's onPostExecute, do       mListener.onUserDetailsReceived(userDetails).
        }
    
        private class DownloaderTask extends AsyncTask<String, Integer, UserDetails> {
            @Override
            protected UserDetails doInBackground(String... params) {
                //Download code
                //In downloading there might go stuff wrong. If so, return null as an easy method without any error handling.
                UserDetails userDetails = new UserDetails("downloadedUsername");
                return userDetails;
            }
    
    
            @Override
            protected void onPostExecute(UserDetails userDetails) {
                if(userDetails == null) {
                    if(mListener != null) {
                        //Something went wrong. Tell the listener.
                        mListener.onUserDetailsError();
                    }               
                } else {
                    if(mListener != null) {
                        //Cool! Lets pass the userDetails to the activity.
                        mListener.onUserDetailsReceiver(userDetails);
                    }
                }
            }   
        }
    }
    
  4. アクティビティに IOnUserDetailsReceivedListener を実装させます。

    public void UserActivity extends Activity implements IOnUserDetailsReceivedListener {
        private UserDetailsDownloader mUserDetailsDownloader;
    
        public void onCreate(...) {
            mUserDetailsDownloader = new UserDetailsDownloader(this);
            mUserDetailsDownloader.downloadUserDetails();
        }
    
        public void onUserDetailsReceived(UserDetails userDetails) {
            //Yeeh we received user data.
        }
    
        public void onUserDetailsError() {
            //Something went wrong. Tell the user?
        }
    }
    
  5. タスクが完了すると、Activities の onUserDetailsReceived メソッドが呼び出され、UserDetails 値オブジェクトが渡されます。これを使用して、必要なことを行うことができます。

于 2013-11-01T13:56:08.663 に答える
2

これがあなたの唯一の問題かどうかはわかりませんが、コメントするには多すぎます。では使用runOnUiThread()しないでくださいdoInBackground()

 runOnUiThread(new Runnable() {
     public void run() {

     //this might cause some SHIT!!!!!!!!!!!! TEST IT!!!
     toastMaker.toast(getBaseContext(), configurationz.ERROR_MESSAGES_SIGNUP_DEVICE_UNABLE_TO_TAKE_PHOTOS, configurationz, Toast.LENGTH_LONG);

    }
});

AsyncTaskこれがhasonPostExecute()とその他のメソッドの理由です...それらはすべて、UI Threadを除いて実行されますdoInBackground()

の代わりにreturn nullreturn成功のand depending on that value, do what you need to inonPostExecute()`.

編集

onPostExecute()宣言doInBackground()の 3 番目に返されるものからパラメータを取得します。したがって、それを変更するか、 aをfromに戻すことができます。parampublic class GetUserDataGetter extends AsyncTask<String, String, String>paramStringonPostExecute()doInBackground()

AsyncTask ドキュメント

于 2013-11-01T13:46:12.553 に答える